home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume89 / unix / rcs.11 < prev    next >
Internet Message Format  |  1989-11-19  |  91KB

  1. Path: xanth!samsung!shadooby!mailrus!cs.utexas.edu!sun-barr!newstop!sun!swap!page
  2. From: page%swap@Sun.COM (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v89i226:  rcs - revision control system, Part11/14
  5. Message-ID: <128102@sun.Eng.Sun.COM>
  6. Date: 19 Nov 89 09:25:50 GMT
  7. Sender: news@sun.Eng.Sun.COM
  8. Lines: 3293
  9. Approved: page@sun.com
  10.  
  11. Submitted-by: rsbx@cbmvax.commodore.com (Raymond S. Brand)
  12. Posting-number: Volume 89, Issue 226
  13. Archive-name: unix/rcs.11
  14.  
  15. # This is a shell archive.
  16. # Remove anything above and including the cut line.
  17. # Then run the rest of the file through 'sh'.
  18. # Unpacked files will be owned by you and have default permissions.
  19. #----cut here-----cut here-----cut here-----cut here----#
  20. #!/bin/sh
  21. # shar: SHell ARchive
  22. # Run the following text through 'sh' to create:
  23. #    rcs/rcs.rcsfiles/rcssyn.c,v
  24. #    rcs/rcs.rcsfiles/rcsutil.c,v
  25. #    rcs/rcs.rcsfiles/rlog.c,v
  26. # This is archive 11 of a 14-part kit.
  27. # This archive created: Sun Nov 19 01:12:11 1989
  28. if `test ! -d rcs`
  29. then
  30.   mkdir rcs
  31.   echo "mkdir rcs"
  32. fi
  33. if `test ! -d rcs/rcs.rcsfiles`
  34. then
  35.   mkdir rcs/rcs.rcsfiles
  36.   echo "mkdir rcs/rcs.rcsfiles"
  37. fi
  38. echo "extracting rcs/rcs.rcsfiles/rcssyn.c,v"
  39. sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rcssyn.c,v
  40. Xhead     4.6;
  41. Xbranch   4.6.2;
  42. Xaccess   ;
  43. Xsymbols  amiga_rcs:4.6.2 cbmvax_source:4.6.1 uunet_june89_dist:4.6;
  44. Xlocks    ; strict;
  45. Xcomment  @ * @;
  46. X
  47. X
  48. X4.6
  49. Xdate     89.05.01.15.13.32;  author narten;  state Exp;
  50. Xbranches 4.6.1.1 4.6.2.1;
  51. Xnext     ;
  52. X
  53. X4.6.1.1
  54. Xdate     89.08.11.01.43.06;  author rsbx;  state Exp;
  55. Xbranches ;
  56. Xnext     ;
  57. X
  58. X4.6.2.1
  59. Xdate     89.10.13.19.19.15;  author rsbx;  state Exp;
  60. Xbranches ;
  61. Xnext     4.6.2.2;
  62. X
  63. X4.6.2.2
  64. Xdate     89.10.15.15.45.04;  author rsbx;  state Exp;
  65. Xbranches ;
  66. Xnext     ;
  67. X
  68. X
  69. Xdesc
  70. X@RCS file input.
  71. X@
  72. X
  73. X
  74. X
  75. X4.6
  76. Xlog
  77. X@checked in with -k by rsbx at 89.08.10.16.23.06.
  78. X@
  79. Xtext
  80. X@/*
  81. X *                     RCS file input
  82. X */
  83. X#ifndef lint
  84. Xstatic char rcsid[]= "$Id: rcssyn.c,v 4.6 89/05/01 15:13:32 narten Exp $ Purdue CS";
  85. X#endif
  86. X/*********************************************************************************
  87. X *                       Syntax Analysis.
  88. X *                       Keyword table
  89. X *                       Testprogram: define SYNDB
  90. X *                       Compatibility with Release 2: define COMPAT2
  91. X *********************************************************************************
  92. X */
  93. X
  94. X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
  95. X * All rights reserved.
  96. X *
  97. X * Redistribution and use in source and binary forms are permitted
  98. X * provided that the above copyright notice and this paragraph are
  99. X * duplicated in all such forms and that any documentation,
  100. X * advertising materials, and other materials related to such
  101. X * distribution and use acknowledge that the software was developed
  102. X * by Walter Tichy.
  103. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  104. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  105. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  106. X *
  107. X * Report all problems and direct all questions to:
  108. X *   rcs-bugs@@cs.purdue.edu
  109. X * 
  110. X
  111. X
  112. X
  113. X
  114. X
  115. X
  116. X
  117. X*/
  118. X
  119. X
  120. X/* $Log:    rcssyn.c,v $
  121. X * Revision 4.6  89/05/01  15:13:32  narten
  122. X * changed copyright header to reflect current distribution rules
  123. X * 
  124. X * Revision 4.5  88/11/08  12:00:37  narten
  125. X * changes from  eggert@@sm.unisys.com (Paul Eggert)
  126. X * 
  127. X * Revision 4.5  88/08/09  19:13:21  eggert
  128. X * Allow cc -R; remove lint.
  129. X * 
  130. X * Revision 4.4  87/12/18  11:46:16  narten
  131. X * more lint cleanups (Guy Harris)
  132. X * 
  133. X * Revision 4.3  87/10/18  10:39:36  narten
  134. X * Updating version numbers. Changes relative to 1.1 actually relative to
  135. X * 4.1
  136. X * 
  137. X * Revision 1.3  87/09/24  14:00:49  narten
  138. X * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  139. X * warnings)
  140. X * 
  141. X * Revision 1.2  87/03/27  14:22:40  jenkins
  142. X * Port to suns
  143. X * 
  144. X * Revision 1.1  84/01/23  14:50:40  kcs
  145. X * Initial revision
  146. X * 
  147. X * Revision 4.1  83/03/28  11:38:49  wft
  148. X * Added parsing and printing of default branch.
  149. X * 
  150. X * Revision 3.6  83/01/15  17:46:50  wft
  151. X * Changed readdelta() to initialize selector and log-pointer.
  152. X * Changed puttree to check for selector==DELETE; putdtext() uses DELNUMFORM.
  153. X *
  154. X * Revision 3.5  82/12/08  21:58:58  wft
  155. X * renamed Commentleader to Commleader.
  156. X *
  157. X * Revision 3.4  82/12/04  13:24:40  wft
  158. X * Added routine gettree(), which updates keeplock after reading the
  159. X * delta tree.
  160. X *
  161. X * Revision 3.3  82/11/28  21:30:11  wft
  162. X * Reading and printing of Suffix removed; version COMPAT2 skips the
  163. X * Suffix for files of release 2 format. Fixed problems with printing nil.
  164. X *
  165. X * Revision 3.2  82/10/18  21:18:25  wft
  166. X * renamed putdeltatext to putdtext.
  167. X *
  168. X * Revision 3.1  82/10/11  19:45:11  wft
  169. X * made sure getc() returns into an integer.
  170. X */
  171. X
  172. X
  173. X
  174. X/*
  175. X#define COMPAT2
  176. X/* version COMPAT2 reads files of the format of release 2 and 3, but
  177. X * generates files of release 3 format. Need not be defined if no
  178. X * old RCS files generated with release 2 exist.
  179. X */
  180. X/*
  181. X#define SYNDB
  182. X/* version SYNDB is for debugging the syntax analysis for RCS files.
  183. X * SYNDB performs additional error checks.
  184. X */
  185. X/*
  186. X#define SYNTEST
  187. X/* version SYNTEST inputs a RCS file and then prints out its internal
  188. X * data structures.
  189. X*/
  190. X
  191. X#include "rcsbase.h"
  192. Xextern FILE * finptr;        /*RCS input file*/
  193. Xextern char * getid();
  194. Xextern struct hshentry * getnum();
  195. Xextern int    getkey();
  196. Xextern int    getlex();
  197. Xextern        readstring();
  198. Xextern        savestring();
  199. X
  200. X/* forward */
  201. Xchar * getkeyval();
  202. X
  203. X/* keyword table */
  204. X
  205. Xchar Kaccess[]   = "access";
  206. Xchar Kauthor[]   = "author";
  207. Xchar Kbranch[]   = "branch";
  208. Xchar Kbranches[] = "branches";
  209. Xchar Kcomment[]  = "comment";
  210. Xchar Kdate[]     = "date";
  211. Xchar Kdesc[]     = "desc";
  212. Xchar Khead[]     = "head";
  213. Xchar Klocks[]    = "locks";
  214. Xchar Klog[]      = "log";
  215. Xchar Knext[]     = "next";
  216. Xchar Kstate[]    = "state";
  217. Xchar Kstrict[]   = "strict";
  218. X#ifdef COMPAT2
  219. Xchar Ksuffix[]   = "suffix";
  220. X#endif
  221. Xchar Ksymbols[]  = "symbols";
  222. Xchar Ktext[]     = "text";
  223. X
  224. X#define COMMLENGTH 20
  225. Xchar              Commleader[COMMLENGTH];
  226. Xchar            * Comment;
  227. Xstruct access   * AccessList;
  228. Xstruct access   * LastAccess;
  229. Xstruct assoc    * Symbols;
  230. Xstruct assoc    * LastSymbol;
  231. Xstruct lock     * Locks;
  232. Xstruct lock     * LastLock;
  233. Xint               StrictLocks;
  234. Xstruct hshentry * Head;
  235. Xstruct hshentry * Dbranch;
  236. Xint               TotalDeltas;
  237. X
  238. X
  239. X
  240. Xgetadmin()
  241. X/* Function: Reads an <admin> and initializes the globals
  242. X * AccessList, LastAccess, Symbols, LastSymbol,
  243. X * Locks, LastLock, StrictLocks, Head, Comment, TotalDeltas;
  244. X */
  245. X{
  246. X        register char   * id;
  247. X        struct access   * newaccess;
  248. X        struct assoc    * newassoc;
  249. X        struct lock     * newlock;
  250. X        struct hshentry * delta;
  251. X
  252. X        Comment="";
  253. X        AccessList=LastAccess=nil;
  254. X        Symbols=LastSymbol=nil;
  255. X        Locks=LastLock=nil;
  256. X        Dbranch = Head = nil;
  257. X        TotalDeltas=0;
  258. X
  259. X        if (!getkey(Khead)) fatserror("Missing head");
  260. X        Head=getnum();
  261. X#       ifdef SYNDB
  262. X        if (Head&&((countnumflds(Head->num)%2)!=0))
  263. X                serror("Delta number required for head");
  264. X#       endif
  265. X        if (!getlex(SEMI)) serror("Missing ';' after head");
  266. X
  267. X        if (getkey(Kbranch)) { /* optional */
  268. X                Dbranch=getnum();
  269. X                if (!getlex(SEMI)) serror("Missing ';' after branch list");
  270. X        }
  271. X
  272. X
  273. X#ifdef COMPAT2
  274. X        /* read suffix. Only in release 2 format */
  275. X        if (getkey(Ksuffix)) {
  276. X                if (nexttok==STRING) {
  277. X                        readstring(); nextlex(); /*through away the suffix*/
  278. X                } elsif(nexttok==ID) {
  279. X                        nextlex();
  280. X                }
  281. X                if (!getlex(SEMI)) serror("Missing ';' after %s",Ksuffix);
  282. X        }
  283. X#endif
  284. X
  285. X        if (!getkey(Kaccess)) fatserror("Missing access list");
  286. X        while (id=getid()) {
  287. X                newaccess = (struct access *)talloc(sizeof(struct access));
  288. X                newaccess->login = id;
  289. X                newaccess->nextaccess = nil;
  290. X                if (AccessList == nil) {
  291. X                        AccessList=LastAccess=newaccess;
  292. X                } else {
  293. X                        LastAccess=LastAccess->nextaccess=newaccess;
  294. X                }
  295. X        }
  296. X        if (!getlex(SEMI)) serror("Missing ';' after access list");
  297. X
  298. X        if (!getkey(Ksymbols)) fatserror("Missing symbols");
  299. X        while (id = getid()) {
  300. X                if (!getlex(COLON))
  301. X                        serror("Missing ':' in symbolic name definition");
  302. X                if (!(delta=getnum())) {
  303. X                        serror("Missing number in symbolic name definition");
  304. X                } else { /*add new pair to association list*/
  305. X                        newassoc=(struct assoc *)talloc(sizeof(struct assoc));
  306. X                        newassoc->symbol=id;
  307. X                        newassoc->delta=delta;
  308. X                        newassoc->nextassoc=nil;
  309. X                        if (Symbols == nil) {
  310. X                                Symbols=LastSymbol=newassoc;
  311. X                        } else {
  312. X                                LastSymbol=LastSymbol->nextassoc=newassoc;
  313. X                        }
  314. X                }
  315. X        }
  316. X        if (!getlex(SEMI)) serror("Missing ';' after symbolic names");
  317. X
  318. X        if (!getkey(Klocks)) serror("Missing locks");
  319. X        while (id = getid()) {
  320. X                if (!getlex(COLON))
  321. X                        serror("Missing ':' in lock");
  322. X                if (!(delta=getnum())) {
  323. X                        serror("Missing number in lock");
  324. X                } else { /*add new pair to lock list*/
  325. X#                       ifdef SYNDB
  326. X                        if ((countnumflds(delta->num)%2)!=0)
  327. X                                serror("Delta number required for lock");
  328. X#                       endif
  329. X                        newlock=(struct lock *)talloc(sizeof(struct lock));
  330. X                        newlock->login=id;
  331. X                        newlock->delta=delta;
  332. X                        newlock->nextlock=nil;
  333. X                        if (Locks == nil) {
  334. X                                Locks=LastLock=newlock;
  335. X                        } else {
  336. X                                LastLock=LastLock->nextlock=newlock;
  337. X                        }
  338. X                }
  339. X        }
  340. X        if (!getlex(SEMI)) serror("Missing ';' after locks");
  341. X        if (!getkey(Kstrict)) {
  342. X                StrictLocks = false;
  343. X        } else {
  344. X                StrictLocks = true;
  345. X                if (!getlex(SEMI)) serror("Missing ';' after keyword %s",Kstrict);
  346. X        }
  347. X        if (getkey(Kcomment) && (nexttok==STRING)) {
  348. X                VOID savestring(Commleader,COMMLENGTH);nextlex();
  349. X                Comment=Commleader;
  350. X                if (!getlex(SEMI)) serror("Missing ';' after %s",Kcomment);
  351. X        }
  352. X}
  353. X
  354. X
  355. X
  356. Xgetdelta()
  357. X/* Function: reads a delta block.
  358. X * returns false if the current block does not start with a number.
  359. X */
  360. X{
  361. X        register struct hshentry * Delta, * num;
  362. X        struct branchhead * LastBranch, * NewBranch;
  363. X
  364. X        if (!(Delta=getnum())) return false;
  365. X#       ifdef SYNDB
  366. X        if ((countnumflds(Delta->num)%2)!=0)
  367. X                serror("Delta number required");
  368. X#       endif
  369. X
  370. X        hshenter = false; /*Don't enter dates into hashtable*/
  371. X        Delta->date = getkeyval(Kdate, NUM, false);
  372. X        hshenter=true;    /*reset hshenter for revision numbers.*/
  373. X
  374. X        Delta->author = getkeyval(Kauthor, ID, false);
  375. X
  376. X        Delta->state = getkeyval(Kstate, ID, true);
  377. X
  378. X        if (!getkey(Kbranches)) fatserror("Missing branches");
  379. X        Delta->branches = LastBranch=nil;
  380. X        while (num=getnum()) {
  381. X#               ifdef SYNDB
  382. X                if ((countnumflds(num->num)%2)!=0)
  383. X                        serror("Delta number required");
  384. X#               endif
  385. X                NewBranch = (struct branchhead *)talloc(sizeof(struct branchhead));
  386. X                NewBranch->hsh = num;
  387. X                NewBranch->nextbranch = nil;
  388. X                if (LastBranch == nil) {
  389. X                        Delta->branches=LastBranch=NewBranch;
  390. X                } else {
  391. X                        LastBranch=LastBranch->nextbranch=NewBranch;
  392. X                }
  393. X        }
  394. X        if (!getlex(SEMI)) serror("Missing ';' after branches");
  395. X
  396. X        if (!getkey(Knext)) fatserror("Missing next");
  397. X        Delta->next=num=getnum();
  398. X#       ifdef SYNDB
  399. X        if (num&&((countnumflds(num->num)%2)!=0))
  400. X                serror("Delta number required");
  401. X#       endif
  402. X        if (!getlex(SEMI)) serror("Missing ';' after next");
  403. X        Delta->log=Delta->lockedby = nil;
  404. X        Delta->selector = '\0';
  405. X        TotalDeltas++;
  406. X        return (true);
  407. X}
  408. X
  409. X
  410. Xgettree()
  411. X/* Function: Reads in the delta tree with getdelta(), then
  412. X * updates the lockedby fields.
  413. X */
  414. X{       struct lock * currlock;
  415. X        while (getdelta());
  416. X        currlock=Locks;
  417. X        while (currlock) {
  418. X                currlock->delta->lockedby = currlock->login;
  419. X                currlock = currlock->nextlock;
  420. X        }
  421. X}
  422. X
  423. X
  424. Xgetdesc(prdesc)
  425. Xint  prdesc;
  426. X/* Function: read in descriptive text
  427. X * nexttok is not advanced afterwards.
  428. X * if prdesc==true, the text is printed to stdout.
  429. X */
  430. X{
  431. X
  432. X        if (!getkey(Kdesc) || (nexttok!=STRING)) fatserror("Missing descriptive text");
  433. X        if (prdesc)
  434. X                printstring();  /*echo string*/
  435. X        else    readstring();   /*skip string*/
  436. X}
  437. X
  438. X
  439. X
  440. X
  441. X
  442. X
  443. Xchar * getkeyval(keyword, token, optional)
  444. Xenum tokens token; char * keyword; int optional;
  445. X/* reads a pair of the form
  446. X * <keyword> <token> ;
  447. X * where token is one of <id> or <num>. optional indicates whether
  448. X * <token> is optional. A pointer to
  449. X * the acutal character string of <id> or <num) is returned.
  450. X * Getkeyval terminates the program on missing keyword or token, continues
  451. X * on missing ;.
  452. X */
  453. X{
  454. X        register char * val;
  455. X
  456. X        if (!getkey(keyword)) {
  457. X                fatserror("Missing %s", keyword);
  458. X        }
  459. X        if (nexttok==token) {
  460. X                val = NextString;
  461. X                nextlex();
  462. X        } else {
  463. X                if (!optional) {fatserror("Missing %s", keyword); }
  464. X                else val = nil;
  465. X        }
  466. X        if (!getlex(SEMI)) serror("Missing ';' after %s",keyword);
  467. X        return(val);
  468. X}
  469. X
  470. X
  471. X
  472. X
  473. Xputadmin(fout)
  474. Xregister FILE * fout;
  475. X/* Function: Print the <admin> node read with getadmin() to file fout.
  476. X * Assumption: Variables AccessList, Symbols, Locks, StrictLocks,
  477. X * and Head have been set.
  478. X */
  479. X{       struct assoc  * curassoc;
  480. X        struct lock   * curlock;
  481. X        struct access * curaccess;
  482. X        register char * sp;
  483. X
  484. X        VOID fputs(Khead,fout); VOID fputs("     ",fout);
  485. X        if (Head) VOID fputs(Head->num,fout);
  486. X
  487. X        VOID fprintf(fout,";\n%s   ",Kbranch);
  488. X        if (Dbranch) VOID fputs(Dbranch->num,fout);
  489. X
  490. X        VOID fprintf(fout,";\n%s  ",Kaccess);
  491. X        curaccess = AccessList;
  492. X        if (curaccess==nil) VOID putc(' ',fout);
  493. X        while (curaccess) {
  494. X               VOID putc(' ',fout);
  495. X               VOID fputs(curaccess->login,fout);
  496. X               curaccess = curaccess->nextaccess;
  497. X        }
  498. X        VOID fprintf(fout,";\n%s ",Ksymbols);
  499. X        curassoc = Symbols;
  500. X        if (curassoc==nil) VOID putc(' ',fout);
  501. X        while (curassoc) {
  502. X               VOID fprintf(fout," %s:%s",curassoc->symbol, curassoc->delta->num);
  503. X               curassoc = curassoc->nextassoc;
  504. X        }
  505. X        VOID fprintf(fout,";\n%s   ",Klocks);
  506. X        curlock = Locks;
  507. X        if (curlock==nil) VOID putc(' ',fout);
  508. X        while (curlock) {
  509. X               VOID fprintf(fout," %s:%s",curlock->login, curlock->delta->num);
  510. X               curlock = curlock->nextlock;
  511. X        }
  512. X        if (StrictLocks) VOID fprintf(fout,"; %s",Kstrict);
  513. X        VOID fprintf(fout,";\n%s  %c",Kcomment,SDELIM);
  514. X        if((sp=Comment)!=nil) {
  515. X               while (*sp) if (putc(*sp++,fout)==SDELIM) VOID putc(SDELIM,fout);
  516. X        }
  517. X        VOID fprintf(fout,"%c;\n\n",SDELIM);
  518. X}
  519. X
  520. X
  521. X
  522. X
  523. Xputdelta(node,fout)
  524. Xregister struct hshentry * node;
  525. Xregister FILE * fout;
  526. X/* Function: prints a <delta> node to fout;
  527. X */
  528. X{      struct branchhead * nextbranch;
  529. X
  530. X        if (node == nil) return;
  531. X
  532. X        VOID fprintf(fout,"\n%s\n",node->num);
  533. X        VOID fprintf(fout,"%s     %s;  %s %s;  %s ",
  534. X                Kdate,node->date,Kauthor,node->author,Kstate);
  535. X        if (node->state!=nil) VOID fputs(node->state,fout);
  536. X        VOID fputs(";\nbranches",fout);
  537. X        nextbranch = node->branches;
  538. X        if (nextbranch==nil) VOID putc(' ',fout);
  539. X        while (nextbranch) {
  540. X               VOID putc(' ',fout);
  541. X               VOID fputs(nextbranch->hsh->num,fout);
  542. X               nextbranch = nextbranch->nextbranch;
  543. X        }
  544. X
  545. X        VOID fprintf(fout,";\n%s     ",Knext);
  546. X        if (node->next!=nil) VOID fputs(node->next->num,fout);
  547. X        VOID fputs(";\n",fout);
  548. X
  549. X}
  550. X
  551. X
  552. X
  553. X
  554. Xputtree(root,fout)
  555. Xstruct hshentry * root;
  556. Xregister FILE * fout;
  557. X/* Function: prints the delta tree in preorder to fout, starting with root.
  558. X */
  559. X{       struct branchhead * nextbranch;
  560. X
  561. X        if (root==nil) return;
  562. X
  563. X        if (root->selector !=DELETE)putdelta(root,fout);
  564. X        /* selector DELETE means deleted; set by rcs -o */
  565. X
  566. X        puttree(root->next,fout);
  567. X
  568. X        nextbranch = root->branches;
  569. X        while (nextbranch) {
  570. X             puttree(nextbranch->hsh,fout);
  571. X             nextbranch = nextbranch->nextbranch;
  572. X        }
  573. X}
  574. X
  575. X
  576. X
  577. Xint putdtext(num,log,srcfilename,fout)
  578. Xchar * num, * log, * srcfilename; FILE * fout;
  579. X/* Function: write a deltatext-node to fout.
  580. X * num points to the deltanumber, log to the logmessage, and
  581. X * sourcefile contains the text. Doubles up all SDELIMs in both the
  582. X * log and the text; Makes sure the log message ends in \n.
  583. X * returns false on error.
  584. X */
  585. X{
  586. X        register char * sp;
  587. X    register int c;
  588. X        register FILE * fin;
  589. X
  590. X        VOID fprintf(fout,DELNUMFORM,num,Klog);
  591. X        /* put log */
  592. X        VOID putc(SDELIM,fout);
  593. X        sp=log;
  594. X        while (*sp) if (putc(*sp++,fout)==SDELIM) VOID putc(SDELIM,fout);
  595. X        if (*(sp-1)!='\n') VOID putc('\n', fout); /*append \n if necessary*/
  596. X        /* put text */
  597. X        VOID fprintf(fout, "%c\n%s\n%c",SDELIM,Ktext,SDELIM);
  598. X        if ((fin=fopen(srcfilename,"r"))==NULL) {
  599. X                error("Can't open source file %s",srcfilename);
  600. X                return false;
  601. X        }
  602. X        while ((c=fgetc(fin))!=EOF) {
  603. X                if (c==SDELIM) VOID putc(SDELIM,fout);   /*double up SDELIM*/
  604. X                VOID putc(c,fout);
  605. X        }
  606. X        VOID putc(SDELIM,fout); VOID putc('\n',fout);
  607. X        VOID fclose(fin);
  608. X        return true;
  609. X}
  610. X
  611. X
  612. X
  613. X#ifdef SYNTEST
  614. X
  615. Xmain(argc,argv)
  616. Xint argc; char * argv[];
  617. X{
  618. X
  619. X        cmdid = "syntest";
  620. X        if (argc<2) {
  621. X                VOID fputs("No input file\n",stderr);
  622. X                exit(-1);
  623. X        }
  624. X        if ((finptr=fopen(argv[1], "r")) == NULL) {
  625. X                faterror("Can't open input file %s\n",argv[1]);
  626. X        }
  627. X        Lexinit();
  628. X        getadmin();
  629. X        putadmin(stdout);
  630. X
  631. X        gettree();
  632. X        puttree(Head,stdout);
  633. X
  634. X        getdesc(true);
  635. X
  636. X        if (nextlex(),nexttok!=EOFILE) {
  637. X                fatserror("Syntax error");
  638. X        }
  639. X        exit(0);
  640. X}
  641. X
  642. X
  643. Xcleanup(){}
  644. X/*dummy*/
  645. X
  646. X
  647. X#endif
  648. X
  649. X@
  650. X
  651. X
  652. X4.6.2.1
  653. Xlog
  654. X@Start of Amiga RCS port branch.
  655. X@
  656. Xtext
  657. X@d5 1
  658. Xa5 5
  659. X<<<<<<< rcssyn.c
  660. Xstatic char rcsid[]= "$Id: rcssyn.c,v 4.6.1.1 89/08/11 01:43:06 rsbx Exp Locker: rsbx $ Purdue CS";
  661. X=======
  662. Xstatic char rcsid[]= "$Id: rcssyn.c,v 1.2 89/09/17 13:36:37 rick Exp $ Purdue CS";
  663. X>>>>>>> 1.2
  664. Xa41 16
  665. X<<<<<<< rcssyn.c
  666. X * Revision 4.6.1.1  89/08/11  01:43:06  rsbx
  667. X * Start of cbmvax RCS source branch.
  668. X * 
  669. X * Revision 4.6  89/05/01  15:13:32  narten
  670. X * checked in with -k by rsbx at 89.08.10.16.23.06.
  671. X=======
  672. X * Revision 1.2  89/09/17  13:36:37  rick
  673. X * Port to AmigaDos done by Rick Schaeffer (ricks@@iscuva.iscs.com)
  674. X * All changes done with conditional compile (#ifdef AMIGA).  This version
  675. X * compiles correctly with Lattice C version 5.02 or later.
  676. X * 
  677. X * Revision 1.2  88/09/03  15:12:39  rick
  678. X * Port to AmigaDos.  All done with conditional compiles
  679. X>>>>>>> 1.2
  680. X * 
  681. X@
  682. X
  683. X
  684. X4.6.2.2
  685. Xlog
  686. X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
  687. Xsources I have here (and are later than the ones Rick used).
  688. X@
  689. Xtext
  690. X@d5 5
  691. Xa9 1
  692. Xstatic char rcsid[]= "$Id: rcssyn.c,v 4.6.2.1 89/10/13 19:19:15 rsbx Exp Locker: rsbx $ Purdue CS";
  693. Xd46 1
  694. Xa46 3
  695. X * Revision 4.6.2.1  89/10/13  19:19:15  rsbx
  696. X * Start of Amiga RCS port branch.
  697. X * 
  698. Xd52 9
  699. X@
  700. X
  701. X
  702. X4.6.1.1
  703. Xlog
  704. X@Start of cbmvax RCS source branch.
  705. X@
  706. Xtext
  707. X@a42 3
  708. X * checked in with -k by rsbx at 89.08.10.16.23.06.
  709. X * 
  710. X * Revision 4.6  89/05/01  15:13:32  narten
  711. X@
  712. SHAR_EOF
  713. echo "extracting rcs/rcs.rcsfiles/rcsutil.c,v"
  714. sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rcsutil.c,v
  715. Xhead     4.6;
  716. Xbranch   4.6.2;
  717. Xaccess   ;
  718. Xsymbols  amiga_rcs:4.6.2 cbmvax_source:4.6.1 uunet_june89_dist:4.6;
  719. Xlocks    ; strict;
  720. Xcomment  @ * @;
  721. X
  722. X
  723. X4.6
  724. Xdate     89.05.01.15.13.40;  author narten;  state Exp;
  725. Xbranches 4.6.1.1 4.6.2.1;
  726. Xnext     ;
  727. X
  728. X4.6.1.1
  729. Xdate     89.08.11.01.43.12;  author rsbx;  state Exp;
  730. Xbranches ;
  731. Xnext     4.6.1.2;
  732. X
  733. X4.6.1.2
  734. Xdate     89.08.11.02.17.29;  author rsbx;  state Exp;
  735. Xbranches ;
  736. Xnext     4.6.1.3;
  737. X
  738. X4.6.1.3
  739. Xdate     89.10.16.15.08.36;  author rsbx;  state Exp;
  740. Xbranches ;
  741. Xnext     ;
  742. X
  743. X4.6.2.1
  744. Xdate     89.10.13.19.19.20;  author rsbx;  state Exp;
  745. Xbranches ;
  746. Xnext     4.6.2.2;
  747. X
  748. X4.6.2.2
  749. Xdate     89.10.15.15.45.09;  author rsbx;  state Exp;
  750. Xbranches ;
  751. Xnext     4.6.2.3;
  752. X
  753. X4.6.2.3
  754. Xdate     89.10.15.18.27.58;  author rsbx;  state Exp;
  755. Xbranches ;
  756. Xnext     4.6.2.4;
  757. X
  758. X4.6.2.4
  759. Xdate     89.10.16.19.01.15;  author rsbx;  state Exp;
  760. Xbranches ;
  761. Xnext     4.6.2.5;
  762. X
  763. X4.6.2.5
  764. Xdate     89.10.16.19.07.28;  author rsbx;  state Exp;
  765. Xbranches ;
  766. Xnext     4.6.2.6;
  767. X
  768. X4.6.2.6
  769. Xdate     89.10.16.23.54.57;  author rsbx;  state Exp;
  770. Xbranches ;
  771. Xnext     4.6.2.7;
  772. X
  773. X4.6.2.7
  774. Xdate     89.10.17.15.04.39;  author rsbx;  state Exp;
  775. Xbranches ;
  776. Xnext     4.6.2.8;
  777. X
  778. X4.6.2.8
  779. Xdate     89.10.18.10.54.09;  author rsbx;  state Exp;
  780. Xbranches ;
  781. Xnext     ;
  782. X
  783. X
  784. Xdesc
  785. X@RCS utilities.
  786. X@
  787. X
  788. X
  789. X4.6
  790. Xlog
  791. X@checked in with -k by rsbx at 89.08.10.16.23.16.
  792. X@
  793. Xtext
  794. X@/*
  795. X *                     RCS utilities
  796. X */
  797. X#ifndef lint
  798. Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6 89/05/01 15:13:40 narten Exp $ Purdue CS";
  799. X#endif
  800. X
  801. X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
  802. X * All rights reserved.
  803. X *
  804. X * Redistribution and use in source and binary forms are permitted
  805. X * provided that the above copyright notice and this paragraph are
  806. X * duplicated in all such forms and that any documentation,
  807. X * advertising materials, and other materials related to such
  808. X * distribution and use acknowledge that the software was developed
  809. X * by Walter Tichy.
  810. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  811. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  812. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  813. X *
  814. X * Report all problems and direct all questions to:
  815. X *   rcs-bugs@@cs.purdue.edu
  816. X * 
  817. X
  818. X
  819. X
  820. X
  821. X
  822. X
  823. X
  824. X*/
  825. X
  826. X
  827. X
  828. X
  829. X/* $Log:    rcsutil.c,v $
  830. X * Revision 4.6  89/05/01  15:13:40  narten
  831. X * changed copyright header to reflect current distribution rules
  832. X * 
  833. X * Revision 4.5  88/11/08  16:01:02  narten
  834. X * corrected use of varargs routines
  835. X * 
  836. X * Revision 4.4  88/11/08  12:00:28  narten
  837. X * changes from  eggert@@sm.unisys.com (Paul Eggert)
  838. X * 
  839. X * Revision 4.4  88/08/09  19:13:24  eggert
  840. X * Check for memory exhaustion.
  841. X * Permit signal handlers to yield either 'void' or 'int'; fix oldSIGINT botch.
  842. X * Use execv(), not system(); yield exit status like diff(1)'s.
  843. X * 
  844. X * Revision 4.3  87/10/18  10:40:22  narten
  845. X * Updating version numbers. Changes relative to 1.1 actually
  846. X * relative to 4.1
  847. X * 
  848. X * Revision 1.3  87/09/24  14:01:01  narten
  849. X * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  850. X * warnings)
  851. X * 
  852. X * Revision 1.2  87/03/27  14:22:43  jenkins
  853. X * Port to suns
  854. X * 
  855. X * Revision 1.1  84/01/23  14:50:43  kcs
  856. X * Initial revision
  857. X * 
  858. X * Revision 4.1  83/05/10  15:53:13  wft
  859. X * Added getcaller() and findlock().
  860. X * Changed catchints() to check SIGINT for SIG_IGN before setting up the signal
  861. X * (needed for background jobs in older shells). Added restoreints().
  862. X * Removed printing of full RCS path from logcommand().
  863. X * 
  864. X * Revision 3.8  83/02/15  15:41:49  wft
  865. X * Added routine fastcopy() to copy remainder of a file in blocks.
  866. X *
  867. X * Revision 3.7  82/12/24  15:25:19  wft
  868. X * added catchints(), ignoreints() for catching and ingnoring interrupts;
  869. X * fixed catchsig().
  870. X *
  871. X * Revision 3.6  82/12/08  21:52:05  wft
  872. X * Using DATEFORM to format dates.
  873. X *
  874. X * Revision 3.5  82/12/04  18:20:49  wft
  875. X * Replaced SNOOPDIR with SNOOPFILE; changed addlock() to update
  876. X * lockedby-field.
  877. X *
  878. X * Revision 3.4  82/12/03  17:17:43  wft
  879. X * Added check to addlock() ensuring only one lock per person.
  880. X * Addlock also returns a pointer to the lock created. Deleted fancydate().
  881. X *
  882. X * Revision 3.3  82/11/27  12:24:37  wft
  883. X * moved rmsema(), trysema(), trydiraccess(), getfullRCSname() to rcsfnms.c.
  884. X * Introduced macro SNOOP so that snoop can be placed in directory other than
  885. X * TARGETDIR. Changed %02d to %.2d for compatibility reasons.
  886. X *
  887. X * Revision 3.2  82/10/18  21:15:11  wft
  888. X * added function getfullRCSname().
  889. X *
  890. X * Revision 3.1  82/10/13  16:17:37  wft
  891. X * Cleanup message is now suppressed in quiet mode.
  892. X */
  893. X
  894. X
  895. X
  896. X
  897. X#include <sys/types.h>
  898. X#include <sys/stat.h>
  899. X#include <signal.h>
  900. X#include "rcsbase.h"
  901. X#include <pwd.h>
  902. X#include <varargs.h>
  903. X
  904. X#if defined(USG) || defined(V4_2BSD)
  905. X#include <fcntl.h>
  906. X#endif
  907. X
  908. X#ifndef V4_2BSD
  909. X#define vfork fork
  910. X#endif
  911. X
  912. Xextern char * bindex();
  913. Xextern FILE * finptr;
  914. Xextern char * RCSfilename;
  915. Xextern char * getlogin();
  916. Xextern struct passwd *getpwuid();
  917. Xextern char * malloc();
  918. X
  919. X
  920. Xchar * talloc(size)
  921. Xunsigned size;
  922. X{
  923. X    char * p;
  924. X    if (!(p = malloc(size))) {
  925. X        faterror("out of memory");
  926. X    }
  927. X    return p;
  928. X}
  929. X
  930. X
  931. X
  932. Xchar * getcaller()
  933. X/* Function: gets the callers login from his uid.
  934. X * If the uid is root, tries to get the true login with getlogin().
  935. X */
  936. X{       char * name;
  937. X    int uid;
  938. X    uid=getuid();
  939. X    if (uid==0) {
  940. X        /* super user; try getlogin() to distinguish */
  941. X        name = getlogin();
  942. X        if (name!=nil && *name!='\0')
  943. X            return name;
  944. X    }
  945. X    return(getpwuid(uid)->pw_name);
  946. X}
  947. X
  948. X
  949. X
  950. Xstruct hshentry * findlock(who,delete)
  951. Xchar * who; int delete;
  952. X/* Finds the first lock held by who and returns a pointer
  953. X * to the locked delta; also removes the lock if delete==true.
  954. X * Returns nil if there is no lock held by who.
  955. X */
  956. X{
  957. X        register struct lock * next, * trail;
  958. X        struct lock dummy;
  959. X
  960. X        dummy.nextlock=next=Locks;
  961. X        trail = &dummy;
  962. X        while (next!=nil) {
  963. X                if(strcmp(who,next->login)==0) break; /*found a lock*/
  964. X                trail=next;
  965. X                next=next->nextlock;
  966. X        }
  967. X        if (next!=nil) {
  968. X        /* found one */
  969. X        if (delete) {
  970. X            /* delete it */
  971. X            trail->nextlock=next->nextlock;
  972. X            Locks=dummy.nextlock;
  973. X            next->delta->lockedby=nil; /* reset locked-by */
  974. X        }
  975. X                return next->delta;
  976. X        } else  return nil;
  977. X}
  978. X
  979. X
  980. X
  981. X
  982. X
  983. X
  984. X
  985. Xstruct lock * addlock(delta,who)
  986. Xstruct hshentry * delta; char * who;
  987. X/* Given a delta, addlock checks whether
  988. X * the delta is locked by somebody other than who.
  989. X * If so, an error message is printed, and false returned.
  990. X * If the delta is not reserved at all, a lock for it is added,
  991. X * and a pointer for the lock returned.
  992. X */
  993. X{
  994. X        struct lock * next;
  995. X
  996. X        next=Locks;
  997. X        while (next!=nil) {
  998. X                if (cmpnum(delta->num,next->delta->num)==0) {
  999. X                        if (strcmp(who,next->login)==0)
  1000. X                                return next;
  1001. X                                /* lock exists already */
  1002. X                        else {
  1003. X                                error("revision %s already locked by %s",
  1004. X                                      delta->num, next->login);
  1005. X                                return false;
  1006. X                        }
  1007. X                } else {
  1008. X                        if (strcmp(who,next->login)==0) {
  1009. X                                error("you already locked %s; only one lock allowed per person.",
  1010. X                                       next->delta->num);
  1011. X                                return false;
  1012. X                        } else {
  1013. X                                next=next->nextlock;
  1014. X                        }
  1015. X                }
  1016. X        }
  1017. X        /* not found; set up new lockblock */
  1018. X        next= (struct lock *) talloc(sizeof (struct lock));
  1019. X        delta->lockedby=next->login=who;
  1020. X        next->delta= delta;
  1021. X        next->nextlock=Locks;
  1022. X        Locks=next;
  1023. X        return next;
  1024. X}
  1025. X
  1026. X
  1027. X
  1028. Xint addsymbol(delta,name,rebind)
  1029. Xstruct hshentry * delta; char * name; int rebind;
  1030. X/* Function: adds a new symbolic name and associates it with node delta.
  1031. X * If name already exists and rebind is true, the name is associated
  1032. X * with the new delta; otherwise, an error message is printed and
  1033. X * false returned. Returns true it successful.
  1034. X */
  1035. X{       register struct assoc * next;
  1036. X        next=Symbols;
  1037. X        while (next!=nil) {
  1038. X                if (strcmp(name,next->symbol)==0) {
  1039. X                        if (rebind) {
  1040. X                                next->delta=delta;
  1041. X                                return true;
  1042. X                        } else {
  1043. X                                error("symbolic name %s already bound to %s",
  1044. X                                        name,next->delta->num);
  1045. X                                return false;
  1046. X                        }
  1047. X                } else  next = next->nextassoc;
  1048. X        }
  1049. X        /* not found; insert new pair. */
  1050. X        next = (struct assoc *) talloc(sizeof(struct assoc));
  1051. X        next->symbol=name;
  1052. X        next->delta=delta;
  1053. X        next->nextassoc=Symbols;
  1054. X        Symbols = next;
  1055. X        return true;
  1056. X}
  1057. X
  1058. X
  1059. X
  1060. X
  1061. Xint checkaccesslist(who)
  1062. Xchar * who;
  1063. X/* function: Returns true if who is the superuser, the owner of the
  1064. X * file, the access list is empty, or who is on the access list.
  1065. X * Prints an error message and returns false otherwise.
  1066. X */
  1067. X{
  1068. X        register struct access * next;
  1069. X        struct stat statbuf;
  1070. X
  1071. X        if ((AccessList==nil) || (strcmp(who,"root")==0))
  1072. X                return true;
  1073. X
  1074. X        next=AccessList;
  1075. X        do {
  1076. X                if (strcmp(who,next->login)==0)
  1077. X                        return true;
  1078. X                next=next->nextaccess;
  1079. X        } while (next!=nil);
  1080. X
  1081. X        VOID fstat(fileno(finptr),&statbuf);  /* get owner of file */
  1082. X        if (getuid() == statbuf.st_uid) return true;
  1083. X
  1084. X        error("User %s not on the access list",who);
  1085. X        return false;
  1086. X}
  1087. X
  1088. X
  1089. Xstatic SIGNAL_TYPE catchsig(s)
  1090. X{
  1091. X    ignoreints();
  1092. X        diagnose("\nRCS: cleaning up\n");
  1093. X        VOID cleanup();
  1094. X    exit(2);
  1095. X#ifdef lint
  1096. X    catchsig(s);
  1097. X#endif
  1098. X}
  1099. X
  1100. Xstatic sig[] = {SIGINT,SIGHUP,SIGQUIT,SIGPIPE,SIGTERM};
  1101. X#define SIGS (sizeof(sig)/sizeof(*sig))
  1102. Xstatic SIGNAL_TYPE (*catcher[SIGS])();
  1103. X  
  1104. X  void catchints()
  1105. X  {
  1106. X    register i;
  1107. X    for (i=SIGS; 0<=--i; )
  1108. X        catcher[i]  =
  1109. X        signal(sig[i],SIG_IGN) == SIG_IGN  ?  SIG_IGN  :  catchsig;
  1110. X    restoreints();
  1111. X  }
  1112. X
  1113. X  void ignoreints()
  1114. X  {
  1115. X    register i;
  1116. X    for (i=SIGS; 0<=--i; )
  1117. X        VOID signal(sig[i], SIG_IGN);
  1118. X  }
  1119. X
  1120. Xvoid restoreints()
  1121. X{
  1122. X    register i;
  1123. X    for (i=SIGS; 0<=--i; )
  1124. X        if (catcher[i] != SIG_IGN)
  1125. X            VOID signal(sig[i], catcher[i]);
  1126. X}
  1127. X
  1128. Xfastcopy(inf,outf)
  1129. XFILE * inf, * outf;
  1130. X/* Function: copies the remainder of file inf to outf. First copies the
  1131. X * rest that is in the IO-buffer of inf character by character, and then
  1132. X * copies the remainder in blocks.
  1133. X */
  1134. X{       char buf[BUFSIZ];
  1135. X        register int rcount, wcount;
  1136. X
  1137. X        /* write the rest of the buffer to outf */
  1138. X        while ((--inf->_cnt)>=0) {
  1139. X                VOID putc(*inf->_ptr++&0377,outf);
  1140. X        }
  1141. X        if (fflush(outf) == EOF) {
  1142. X        writeerror();
  1143. X    }
  1144. X
  1145. X        /*now read the rest of the file in blocks*/
  1146. X        while ((rcount=read(fileno(inf),buf,BUFSIZ))>0) {
  1147. X                wcount=write(fileno(outf),buf,rcount);
  1148. X                if (wcount!=rcount) {
  1149. X                    writeerror();
  1150. X                }
  1151. X        }
  1152. X}
  1153. X
  1154. X
  1155. X
  1156. X
  1157. X
  1158. X
  1159. X#ifdef SNOOPFILE
  1160. X
  1161. X#include "time.h"
  1162. Xextern struct tm* localtime();
  1163. Xextern long time();
  1164. X
  1165. Xlogcommand(commandname,delta, sequence,login)
  1166. Xchar* commandname; struct hshentry * delta, * sequence[];char * login;
  1167. X/* Function: start a process to write the file that
  1168. X * logs the RCS command.
  1169. X * Each line in the log file contains the following information:
  1170. X * operation, revision(r), backward deltas applied(b), forward deltas applied(f),
  1171. X * total deltas present(t), creation date of delta(d), date of operation(o),
  1172. X * login of caller, RCS file name.
  1173. X */
  1174. X{
  1175. X        char logline[200];
  1176. X        char curdate[datelength];
  1177. X    char *inoutargs[5];
  1178. X        register int i, backward, forward;
  1179. X        long clock;
  1180. X        struct tm * tm;
  1181. X
  1182. X        clock=time((long *)0);
  1183. X        tm=localtime(&clock);
  1184. X
  1185. X        VOID sprintf(curdate,DATEFORM,
  1186. X                tm->tm_year, tm->tm_mon+1, tm->tm_mday,
  1187. X                tm->tm_hour, tm->tm_min, tm->tm_sec);
  1188. X
  1189. X        i= backward=forward=0;
  1190. X        while(sequence[i]!=nil) {  /* count deltas to be applied*/
  1191. X        if (countnumflds(sequence[i]->num) == 2)
  1192. X                backward++;  /* reverse delta */
  1193. X        else    forward++;   /* branch delta  */
  1194. X        i++;
  1195. X        }
  1196. X    VOID sprintf(logline,"%s %10sr %3db %3df %3dt %sc %so %s %s",
  1197. X        commandname,delta->num,backward,forward,TotalDeltas,delta->date,
  1198. X        curdate,login,bindex(getfullRCSname(),'/'));
  1199. X    inoutargs[0] = nil;
  1200. X    inoutargs[1] = nil;
  1201. X    inoutargs[2] = SNOOP;
  1202. X    inoutargs[3] = logline;
  1203. X    inoutargs[4] = nil;
  1204. X    VOID run_back(inoutargs);
  1205. X}
  1206. X#endif
  1207. X
  1208. X
  1209. Xstatic int fdreopen(fd, file, flags, mode)
  1210. X    char *file;
  1211. X{
  1212. X    int newfd;
  1213. X    VOID close(fd);
  1214. X    newfd = flags==-1 ? creat(file,mode) : open(file,flags,mode);
  1215. X    if (newfd < 0  ||  newfd == fd)
  1216. X        return newfd;
  1217. X#ifdef F_DUPFD
  1218. X    fd = fcntl(newfd, F_DUPFD, fd);
  1219. X#else
  1220. X    fd = dup2(newfd, fd);
  1221. X#endif
  1222. X    VOID close(newfd);
  1223. X    return fd;
  1224. X}
  1225. X
  1226. Xstatic void tryopen(fd,file,flags)
  1227. X    char *file;
  1228. X{
  1229. X    if (file  &&  fdreopen(fd,file,flags,0600) != fd) {
  1230. X        VOID write(fileno(stderr), file, strlen(file));
  1231. X        VOID write(fileno(stderr), ": cannot open\n", 14);
  1232. X        _exit(2);
  1233. X    }
  1234. X}
  1235. X
  1236. X/*
  1237. X/* Run in the background a command specified by the strings in 'inoutargs'.
  1238. X/* inoutargs[0], if nonnil, is the name of the input file.
  1239. X/* inoutargs[1], if nonnil, is the name of the output file.
  1240. X/* inoutargs[2..] form the command to be run in the background.
  1241. X/*/
  1242. Xstatic int run_back(inoutargs)
  1243. X    register char **inoutargs;
  1244. X{
  1245. X    int pid;
  1246. X    if (fflush(stdout) == EOF  ||  fflush(stderr) == EOF)
  1247. X        return -1;
  1248. X    if (!(pid = vfork())) {
  1249. X        tryopen(fileno(stdin), inoutargs[0], 0);
  1250. X        tryopen(fileno(stdout), inoutargs[1], -1);
  1251. X        VOID execv(inoutargs[2], &inoutargs[2]);
  1252. X        inoutargs[1] = "/bin/sh";
  1253. X        VOID execv(inoutargs[1], &inoutargs[1]);
  1254. X        VOID write(fileno(stderr), "/bin/sh: not found\n", 19);
  1255. X        _exit(2);
  1256. X    }
  1257. X    return pid;
  1258. X}
  1259. X
  1260. X#define CARGSMAX 20
  1261. X/*
  1262. X/* Run a command.
  1263. X/* The first two arguments are the input and output files (if nonnil);
  1264. X/* the rest specify the command and its arguments.
  1265. X/*/
  1266. Xint run(va_alist)
  1267. X    va_dcl
  1268. X{
  1269. X    va_list ap;
  1270. X    int pid, wstatus, w;
  1271. X    char *rgargs[CARGSMAX];
  1272. X    register i = 0;
  1273. X    va_start(ap);
  1274. X    rgargs[0] = va_arg(ap, char *);
  1275. X    rgargs[1] = va_arg(ap, char *);
  1276. X    for (i =2; i< CARGSMAX; i++) {
  1277. X        rgargs[i] = va_arg(ap, char *);
  1278. X        if (rgargs[i] == NULL)
  1279. X        break;
  1280. X    }
  1281. X    va_end(ap);
  1282. X    pid = run_back(rgargs);
  1283. X    if (pid < 0)
  1284. X        return pid;
  1285. X    for (;;)
  1286. X        if ((w = wait(&wstatus)) < 0)
  1287. X            return w;
  1288. X        else if (w == pid)
  1289. X            return wstatus;
  1290. X}
  1291. X@
  1292. X
  1293. X
  1294. X4.6.2.1
  1295. Xlog
  1296. X@Start of Amiga RCS port branch.
  1297. X@
  1298. Xtext
  1299. X@d5 1
  1300. Xa5 5
  1301. X<<<<<<< rcsutil.c
  1302. Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6.1.2 89/08/11 02:17:29 rsbx Exp Locker: rsbx $ Purdue CS";
  1303. X=======
  1304. Xstatic char rcsid[]= "$Id: rcsutil.c,v 1.2 89/09/17 13:36:49 rick Exp $ Purdue CS";
  1305. X>>>>>>> 1.2
  1306. Xa36 14
  1307. X<<<<<<< rcsutil.c
  1308. X * Revision 4.6.1.2  89/08/11  02:17:29  rsbx
  1309. X * Changed catchints() to compile on cbmvax.
  1310. X=======
  1311. X * Revision 1.2  89/09/17  13:36:49  rick
  1312. X * Port to AmigaDos done by Rick Schaeffer (ricks@@iscuva.iscs.com)
  1313. X * All changes done with conditional compile (#ifdef AMIGA).  This version
  1314. X * compiles correctly with Lattice C version 5.02 or later.
  1315. X>>>>>>> 1.2
  1316. X * 
  1317. X<<<<<<< rcsutil.c
  1318. X * Revision 4.6.1.1  89/08/11  01:43:12  rsbx
  1319. X * Start of cbmvax RCS source branch.
  1320. X * 
  1321. Xa37 3
  1322. X * checked in with -k by rsbx at 89.08.10.16.23.16.
  1323. X * 
  1324. X * Revision 4.6  89/05/01  15:13:40  narten
  1325. Xa50 11
  1326. X=======
  1327. X * Revision 1.4  89/09/16  09:43:48  rick
  1328. X * Modified AMIGA changes to work with Lattice C
  1329. X * 
  1330. X * Revision 1.3  88/09/03  17:16:22  rick
  1331. X * Make fastcopy really fast for AmigaDos
  1332. X * 
  1333. X * Revision 1.2  88/09/03  15:12:57  rick
  1334. X * Port to AmigaDos.  All done with conditional compiles
  1335. X * 
  1336. X>>>>>>> 1.2
  1337. Xd103 1
  1338. Xa103 1
  1339. X#ifndef AMIGA
  1340. Xd107 1
  1341. Xa108 1
  1342. X<<<<<<< rcsutil.c
  1343. Xa113 7
  1344. X=======
  1345. X#else
  1346. X#include "stat.h"
  1347. X#include <signal.h>
  1348. X#endif
  1349. X#include "rcsbase.h"
  1350. X>>>>>>> 1.2
  1351. Xa125 8
  1352. X<<<<<<< rcsutil.c
  1353. X=======
  1354. X#ifdef AMIGA
  1355. Xshort    oldSIGINT;
  1356. X#else
  1357. Xint    (*oldSIGINT)();         /* saves the original value for SIGINT */
  1358. X#endif
  1359. X>>>>>>> 1.2
  1360. Xa126 1
  1361. X<<<<<<< rcsutil.c
  1362. Xa135 6
  1363. X=======
  1364. X#ifdef AMIGA
  1365. Xchar *getcaller()
  1366. X{
  1367. X    char *getenv();
  1368. X>>>>>>> 1.2
  1369. Xa136 1
  1370. X<<<<<<< rcsutil.c
  1371. Xa138 5
  1372. X=======
  1373. X    return(getenv("LOGNAME"));
  1374. X}
  1375. X#else
  1376. X>>>>>>> 1.2
  1377. Xa153 1
  1378. X#endif
  1379. Xd156 1
  1380. Xa287 3
  1381. X#ifdef AMIGA
  1382. X        return true;
  1383. X#else
  1384. Xa292 1
  1385. X#endif
  1386. Xa294 1
  1387. X<<<<<<< rcsutil.c
  1388. Xa298 31
  1389. X=======
  1390. X#ifdef AMIGA
  1391. X
  1392. Xcatchsig()
  1393. X{
  1394. X    diagnose("\nRCS: cleaning up\n");
  1395. X    VOID cleanup();
  1396. X    exit(1);
  1397. X}
  1398. X
  1399. Xvoid catchints()
  1400. X{
  1401. X    signal(SIGINT,catchsig);
  1402. X}
  1403. X
  1404. Xvoid ignoreints()
  1405. X{
  1406. X    signal(SIGINT,SIG_IGN);
  1407. X}
  1408. X
  1409. Xvoid restoreints()
  1410. X{
  1411. X    signal(SIGINT,catchsig);
  1412. X}
  1413. X
  1414. X#else
  1415. X
  1416. Xcatchsig(sig)
  1417. X{
  1418. X    VOID signal(sig, SIG_IGN);
  1419. X>>>>>>> 1.2
  1420. Xd315 2
  1421. Xa316 4
  1422. X        if (signal(sig[i],SIG_IGN) == SIG_IGN)
  1423. X        catcher[i] = SIG_IGN;
  1424. X        else
  1425. X        catcher[i] = catchsig;
  1426. Xa333 1
  1427. X#endif
  1428. Xa334 1
  1429. X<<<<<<< rcsutil.c
  1430. Xa335 27
  1431. X=======
  1432. X#ifdef AMIGA
  1433. X#define AMIGABUF (4 *1024)
  1434. Xfastcopy(inf,outf)
  1435. XFILE *inf,*outf;
  1436. X{
  1437. X    static char buf[AMIGABUF];
  1438. X    register int rcount, wcount;
  1439. X    int infd,outfd;
  1440. X
  1441. X    while (inf->_rcnt--)
  1442. X        putc(*inf->_ptr++,outf);
  1443. X    fflush(outf);
  1444. X    infd = fileno(inf);
  1445. X    outfd = fileno(outf);
  1446. X
  1447. X    while ((rcount = read(infd,buf,AMIGABUF)) > 0) {
  1448. X        if (rcount) {
  1449. X            wcount = write(outfd,buf,rcount);
  1450. X            if (wcount!=rcount)
  1451. X                faterror("write error");
  1452. X        }
  1453. X    }
  1454. X}
  1455. X#else
  1456. Xfastcopy(inf,outf)
  1457. X>>>>>>> 1.2
  1458. Xa359 4
  1459. X<<<<<<< rcsutil.c
  1460. X=======
  1461. X#endif
  1462. X>>>>>>> 1.2
  1463. X@
  1464. X
  1465. X
  1466. X4.6.2.2
  1467. Xlog
  1468. X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
  1469. Xsources I have here (and are later than the ones Rick used).
  1470. X@
  1471. Xtext
  1472. X@d5 5
  1473. Xa9 1
  1474. Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6.2.1 89/10/13 19:19:20 rsbx Exp Locker: rsbx $ Purdue CS";
  1475. Xd41 1
  1476. Xa41 3
  1477. X * Revision 4.6.2.1  89/10/13  19:19:20  rsbx
  1478. X * Start of Amiga RCS port branch.
  1479. X * 
  1480. Xd44 6
  1481. Xd51 1
  1482. Xd72 11
  1483. Xd140 2
  1484. Xd146 1
  1485. Xa146 1
  1486. X
  1487. Xa150 1
  1488. X
  1489. Xd152 1
  1490. Xa153 6
  1491. X#ifdef STDARGS
  1492. X#include <stdarg.h>
  1493. X#else
  1494. X#include <varargs.h>
  1495. X#endif
  1496. X
  1497. Xd165 2
  1498. Xd168 1
  1499. Xa168 2
  1500. Xextern int run_back(char **inoutargs);
  1501. X/* short    oldSIGINT; */
  1502. Xd172 1
  1503. Xd174 1
  1504. Xd184 1
  1505. Xa184 2
  1506. X
  1507. X
  1508. Xd189 6
  1509. Xd198 1
  1510. Xa335 1
  1511. X#ifndef AMIGA
  1512. Xd337 1
  1513. Xa337 1
  1514. X#endif
  1515. Xd359 6
  1516. Xd367 1
  1517. Xa367 1
  1518. Xstatic SIGNAL_TYPE catchsig()
  1519. Xd391 1
  1520. Xa391 1
  1521. Xstatic SIGNAL_TYPE catchsig(s)
  1522. Xd393 2
  1523. Xa394 1
  1524. X    ignoreints();
  1525. Xd407 1
  1526. Xa407 1
  1527. Xvoid catchints()
  1528. Xd418 1
  1529. Xa418 1
  1530. Xvoid ignoreints()
  1531. Xd434 3
  1532. Xd462 1
  1533. Xd487 2
  1534. Xd490 1
  1535. Xd546 1
  1536. Xa546 1
  1537. X#ifndef AMIGA
  1538. Xa596 1
  1539. X#endif
  1540. Xa598 1
  1541. X#ifdef STDARGS
  1542. Xd600 4
  1543. Xa603 34
  1544. X * Run a command.
  1545. X * The first two arguments are the input and output files (if nonnil);
  1546. X * the rest specify the command and its arguments.
  1547. X */
  1548. Xint run(char *arg0, char *arg1, ...)
  1549. X{
  1550. X    va_list ap;
  1551. X    int pid, wstatus, w;
  1552. X    char *rgargs[CARGSMAX];
  1553. X    register i;
  1554. X    va_start(ap, arg1);
  1555. X    rgargs[0] = arg0;
  1556. X    rgargs[1] = arg1;
  1557. X    for (i =2; i< CARGSMAX; i++) {
  1558. X        rgargs[i] = va_arg(ap, char *);
  1559. X        if (rgargs[i] == NULL)
  1560. X        break;
  1561. X    }
  1562. X    va_end(ap);
  1563. X    pid = run_back(rgargs);
  1564. X    if (pid < 0)
  1565. X        return pid;
  1566. X    for (;;)
  1567. X        if ((w = wait(&wstatus)) < 0)
  1568. X            return w;
  1569. X        else if (w == pid)
  1570. X            return wstatus;
  1571. X}
  1572. X#else
  1573. X/*
  1574. X * Run a command.
  1575. X * The first two arguments are the input and output files (if nonnil);
  1576. X * the rest specify the command and its arguments.
  1577. X */
  1578. Xa628 1
  1579. X#endif
  1580. X@
  1581. X
  1582. X
  1583. X4.6.2.3
  1584. Xlog
  1585. X@More changes to make Amiga port work.
  1586. X@
  1587. Xtext
  1588. X@d5 1
  1589. Xa5 1
  1590. Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6.2.2 89/10/15 15:45:09 rsbx Exp $ Purdue CS";
  1591. Xa36 4
  1592. X * Revision 4.6.2.2  89/10/15  15:45:09  rsbx
  1593. X * Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
  1594. X * sources I have here (and are later than the ones Rick used).
  1595. X * 
  1596. Xa167 2
  1597. Xchar *getenv();
  1598. Xstatic char *unknownname = "Unknown";
  1599. Xd170 2
  1600. Xa171 8
  1601. X    char *name;
  1602. X    name = getenv("LOGNAME");
  1603. X
  1604. X    if ((name == NULL) || (*name == '\0'))
  1605. X        {
  1606. X        return unknownname;
  1607. X        }
  1608. X    return name;
  1609. X@
  1610. X
  1611. X
  1612. X4.6.2.4
  1613. Xlog
  1614. X@run() moved from rcsutil.c to amiga.c and made to work.
  1615. X@
  1616. Xtext
  1617. X@d5 1
  1618. Xa5 1
  1619. Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6.1.3 89/10/16 15:08:36 rsbx Exp $ Purdue CS";
  1620. Xa36 3
  1621. X * Revision 4.6.2.3  89/10/15  18:27:58  rsbx
  1622. X * More changes to make Amiga port work.
  1623. X * 
  1624. Xd153 6
  1625. Xd571 1
  1626. Xa634 1
  1627. X#endif
  1628. X@
  1629. X
  1630. X
  1631. X4.6.2.5
  1632. Xlog
  1633. X@Changed file path handling to deal with Amiga file path sematics.
  1634. X@
  1635. Xtext
  1636. X@a36 3
  1637. X * Revision 4.6.1.3  89/10/16  15:08:36  rsbx
  1638. X * run() move from rcsutil.c to amiga.c and made to work.
  1639. X * 
  1640. Xd122 1
  1641. Xa122 4
  1642. X#ifdef AMIGA
  1643. X#include "stat.h"
  1644. X#include <signal.h>
  1645. X#else
  1646. Xd132 3
  1647. Xd149 1
  1648. Xd430 3
  1649. Xa432 3
  1650. X        if (wcount!=rcount)
  1651. X                    faterror("write error");
  1652. X            }
  1653. Xd507 1
  1654. Xa507 1
  1655. X        curdate,login,fnamepart(getfullRCSname()));
  1656. X@
  1657. X
  1658. X
  1659. X4.6.2.6
  1660. Xlog
  1661. X@Changes to getcaller().
  1662. X@
  1663. Xtext
  1664. X@d5 1
  1665. Xa5 1
  1666. Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6.2.5 89/10/16 19:07:28 rsbx Exp $ Purdue CS";
  1667. Xa36 3
  1668. X * Revision 4.6.2.5  89/10/16  19:07:28  rsbx
  1669. X * Changed file path handling to deal with Amiga file path sematics.
  1670. X * 
  1671. Xa140 1
  1672. X#include <ctype.h>
  1673. Xd176 1
  1674. Xa176 2
  1675. X    char *sp;
  1676. X    char c;
  1677. Xd178 3
  1678. Xa180 18
  1679. X    sp = name = getenv("LOGNAME");
  1680. X
  1681. X#ifdef TODO
  1682. X/* check for ethernet user/hostname */
  1683. X#endif
  1684. X    
  1685. X    if (sp) {
  1686. X        while ((c = *sp) && (isascii(c))) {
  1687. X            switch (ctab[c]) {
  1688. X                case IDCHAR:
  1689. X                case LETTER:
  1690. X                case DIGIT:
  1691. X                    sp++;
  1692. X                    continue;
  1693. X                default:
  1694. X                    *sp = '\0';
  1695. X                    break;
  1696. X            }
  1697. Xa181 5
  1698. X    }
  1699. X
  1700. X    if ((name == NULL) || (*name == '\0')) {
  1701. X        return unknownname;
  1702. X    }
  1703. X@
  1704. X
  1705. X
  1706. X4.6.2.7
  1707. Xlog
  1708. X@Yet more changes to getcaller().
  1709. X@
  1710. Xtext
  1711. X@d5 1
  1712. Xa5 1
  1713. Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6.2.6 89/10/16 23:54:57 rsbx Exp $ Purdue CS";
  1714. Xa36 3
  1715. X * Revision 4.6.2.6  89/10/16  23:54:57  rsbx
  1716. X * Changes to getcaller().
  1717. X * 
  1718. Xd183 1
  1719. Xa183 3
  1720. X    if (!(name = getenv("LOGNAME"))) {
  1721. X        return unknownname;
  1722. X    }
  1723. Xd188 13
  1724. Xa200 11
  1725. X    sp =name;
  1726. X    while ((c = *sp) && (isascii(c))) {
  1727. X        switch (ctab[c]) {
  1728. X            case IDCHAR:
  1729. X            case LETTER:
  1730. X            case DIGIT:
  1731. X                sp++;
  1732. X                continue;
  1733. X            default:
  1734. X                *sp = '\0';
  1735. X                break;
  1736. Xd204 1
  1737. Xa204 3
  1738. X
  1739. X    if (*name == '\0') {
  1740. X        free(name);
  1741. Xd207 1
  1742. Xa207 5
  1743. X
  1744. X    sp = talloc(sp-name+1);
  1745. X    strcpy(sp, name);
  1746. X    free(name);
  1747. X    return sp;
  1748. X@
  1749. X
  1750. X
  1751. X4.6.2.8
  1752. Xlog
  1753. X@LOGNAME changed to USERNAME. Still need to check the Ameristar software
  1754. Xfor username.
  1755. X@
  1756. Xtext
  1757. X@d5 1
  1758. Xa5 1
  1759. Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6.2.7 89/10/17 15:04:39 rsbx Exp $ Purdue CS";
  1760. Xa36 3
  1761. X * Revision 4.6.2.7  89/10/17  15:04:39  rsbx
  1762. X * Yet more changes to getcaller().
  1763. X * 
  1764. Xd186 1
  1765. Xa186 1
  1766. X    if (!(name = getenv("USERNAME"))) {
  1767. X@
  1768. X
  1769. X
  1770. X4.6.1.1
  1771. Xlog
  1772. X@Start of cbmvax RCS source branch.
  1773. X@
  1774. Xtext
  1775. X@a37 3
  1776. X * checked in with -k by rsbx at 89.08.10.16.23.16.
  1777. X * 
  1778. X * Revision 4.6  89/05/01  15:13:40  narten
  1779. X@
  1780. X
  1781. X
  1782. X4.6.1.2
  1783. Xlog
  1784. X@Changed catchints() to compile on cbmvax.
  1785. X@
  1786. Xtext
  1787. X@d5 1
  1788. Xa5 1
  1789. Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6.1.1 89/08/11 01:43:12 rsbx Exp Locker: rsbx $ Purdue CS";
  1790. Xa36 3
  1791. X * Revision 4.6.1.1  89/08/11  01:43:12  rsbx
  1792. X * Start of cbmvax RCS source branch.
  1793. X * 
  1794. Xd318 2
  1795. Xa319 4
  1796. X        if (signal(sig[i],SIG_IGN) == SIG_IGN)
  1797. X        catcher[i] = SIG_IGN;
  1798. X        else
  1799. X        catcher[i] = catchsig;
  1800. X@
  1801. X
  1802. X
  1803. X4.6.1.3
  1804. Xlog
  1805. X@run() move from rcsutil.c to amiga.c and made to work.
  1806. X@
  1807. Xtext
  1808. X@d5 1
  1809. Xa5 1
  1810. Xstatic char rcsid[]= "$Id: rcsutil.c,v 4.6.2.3 89/10/15 18:27:58 rsbx Exp $ Purdue CS";
  1811. Xa36 13
  1812. X * Revision 4.6.2.3  89/10/15  18:27:58  rsbx
  1813. X * More changes to make Amiga port work.
  1814. X * 
  1815. X * Revision 4.6.2.2  89/10/15  15:45:09  rsbx
  1816. X * Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
  1817. X * sources I have here (and are later than the ones Rick used).
  1818. X * 
  1819. X * Revision 4.6.2.1  89/10/13  19:19:20  rsbx
  1820. X * Start of Amiga RCS port branch.
  1821. X * 
  1822. X * Revision 4.6.1.2  89/08/11  02:17:29  rsbx
  1823. X * Changed catchints() to compile on cbmvax.
  1824. X * 
  1825. Xd109 1
  1826. Xa109 1
  1827. X#ifndef AMIGA
  1828. Xd113 1
  1829. Xd115 1
  1830. Xa120 13
  1831. X#else
  1832. X#include "stat.h"
  1833. X#include <signal.h>
  1834. X#endif
  1835. X
  1836. X#include "rcsbase.h"
  1837. X
  1838. X#ifdef STDARGS
  1839. X#include <stdarg.h>
  1840. X#else
  1841. X#include <varargs.h>
  1842. X#endif
  1843. X
  1844. Xa143 7
  1845. X#ifdef AMIGA
  1846. Xchar *getenv();
  1847. Xstatic char *unknownname = "Unknown";
  1848. Xchar *getcaller()
  1849. X{
  1850. X    char *name;
  1851. X    name = getenv("LOGNAME");
  1852. Xa144 7
  1853. X    if ((name == NULL) || (*name == '\0'))
  1854. X        {
  1855. X        return unknownname;
  1856. X        }
  1857. X    return name;
  1858. X}
  1859. X#else
  1860. Xa159 1
  1861. X#endif
  1862. Xd162 1
  1863. Xa281 1
  1864. X#ifndef AMIGA
  1865. Xd283 1
  1866. Xa283 1
  1867. X#endif
  1868. Xa293 3
  1869. X#ifdef AMIGA
  1870. X        return true;
  1871. X#else
  1872. Xa298 1
  1873. X#endif
  1874. Xa300 1
  1875. X#ifdef AMIGA
  1876. Xa301 24
  1877. Xstatic SIGNAL_TYPE catchsig()
  1878. X{
  1879. X    diagnose("\nRCS: cleaning up\n");
  1880. X    VOID cleanup();
  1881. X    exit(1);
  1882. X}
  1883. X
  1884. Xvoid catchints()
  1885. X{
  1886. X    signal(SIGINT,catchsig);
  1887. X}
  1888. X
  1889. Xvoid ignoreints()
  1890. X{
  1891. X    signal(SIGINT,SIG_IGN);
  1892. X}
  1893. X
  1894. Xvoid restoreints()
  1895. X{
  1896. X    signal(SIGINT,catchsig);
  1897. X}
  1898. X
  1899. X#else
  1900. X
  1901. Xd317 1
  1902. Xa317 1
  1903. Xvoid catchints()
  1904. Xd328 1
  1905. Xa328 1
  1906. Xvoid ignoreints()
  1907. Xa341 1
  1908. X#endif
  1909. Xa342 2
  1910. X#ifdef AMIGA
  1911. X#define AMIGABUF (4 *1024)
  1912. Xa343 22
  1913. XFILE *inf,*outf;
  1914. X{
  1915. X    static char buf[AMIGABUF];
  1916. X    register int rcount, wcount;
  1917. X    int infd,outfd;
  1918. X
  1919. X    while (inf->_rcnt--)
  1920. X        putc(*inf->_ptr++,outf);
  1921. X    fflush(outf);
  1922. X    infd = fileno(inf);
  1923. X    outfd = fileno(outf);
  1924. X
  1925. X    while ((rcount = read(infd,buf,AMIGABUF)) > 0) {
  1926. X        if (rcount) {
  1927. X            wcount = write(outfd,buf,rcount);
  1928. X            if (wcount!=rcount)
  1929. X                faterror("write error");
  1930. X        }
  1931. X    }
  1932. X}
  1933. X#else
  1934. Xfastcopy(inf,outf)
  1935. Xa367 1
  1936. X#endif
  1937. Xd423 1
  1938. Xa423 1
  1939. X#ifndef AMIGA
  1940. Xa475 1
  1941. X#ifdef STDARGS
  1942. Xd477 4
  1943. Xa480 34
  1944. X * Run a command.
  1945. X * The first two arguments are the input and output files (if nonnil);
  1946. X * the rest specify the command and its arguments.
  1947. X */
  1948. Xint run(char *arg0, char *arg1, ...)
  1949. X{
  1950. X    va_list ap;
  1951. X    int pid, wstatus, w;
  1952. X    char *rgargs[CARGSMAX];
  1953. X    register i;
  1954. X    va_start(ap, arg1);
  1955. X    rgargs[0] = arg0;
  1956. X    rgargs[1] = arg1;
  1957. X    for (i =2; i< CARGSMAX; i++) {
  1958. X        rgargs[i] = va_arg(ap, char *);
  1959. X        if (rgargs[i] == NULL)
  1960. X        break;
  1961. X    }
  1962. X    va_end(ap);
  1963. X    pid = run_back(rgargs);
  1964. X    if (pid < 0)
  1965. X        return pid;
  1966. X    for (;;)
  1967. X        if ((w = wait(&wstatus)) < 0)
  1968. X            return w;
  1969. X        else if (w == pid)
  1970. X            return wstatus;
  1971. X}
  1972. X#else
  1973. X/*
  1974. X * Run a command.
  1975. X * The first two arguments are the input and output files (if nonnil);
  1976. X * the rest specify the command and its arguments.
  1977. X */
  1978. Xa505 2
  1979. X#endif
  1980. X#endif
  1981. X@
  1982. SHAR_EOF
  1983. echo "extracting rcs/rcs.rcsfiles/rlog.c,v"
  1984. sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rlog.c,v
  1985. Xhead     4.7;
  1986. Xbranch   4.7.2;
  1987. Xaccess   ;
  1988. Xsymbols  amiga_rcs:4.7.2 cbmvax_source:4.7.1 uunet_june89_dist:4.7;
  1989. Xlocks    ; strict;
  1990. Xcomment  @ * @;
  1991. X
  1992. X
  1993. X4.7
  1994. Xdate     89.05.01.15.13.48;  author narten;  state Exp;
  1995. Xbranches 4.7.1.1 4.7.2.1;
  1996. Xnext     ;
  1997. X
  1998. X4.7.1.1
  1999. Xdate     89.08.11.01.43.14;  author rsbx;  state Exp;
  2000. Xbranches ;
  2001. Xnext     ;
  2002. X
  2003. X4.7.2.1
  2004. Xdate     89.10.13.19.19.26;  author rsbx;  state Exp;
  2005. Xbranches ;
  2006. Xnext     4.7.2.2;
  2007. X
  2008. X4.7.2.2
  2009. Xdate     89.10.15.15.45.14;  author rsbx;  state Exp;
  2010. Xbranches ;
  2011. Xnext     ;
  2012. X
  2013. X
  2014. Xdesc
  2015. X@RLOG operation.
  2016. X@
  2017. X
  2018. X
  2019. X
  2020. X4.7
  2021. Xlog
  2022. X@checked in with -k by rsbx at 89.08.10.16.23.28.
  2023. X@
  2024. Xtext
  2025. X@/*
  2026. X *                       RLOG    operation
  2027. X */
  2028. X#ifndef lint
  2029. Xstatic char rcsid[]=
  2030. X"$Header: /usr/src/local/bin/rcs/src/RCS/rlog.c,v 4.7 89/05/01 15:13:48 narten Exp $ Purdue CS";
  2031. X#endif
  2032. X/*****************************************************************************
  2033. X *                       print contents of RCS files
  2034. X *****************************************************************************
  2035. X */
  2036. X
  2037. X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
  2038. X * All rights reserved.
  2039. X *
  2040. X * Redistribution and use in source and binary forms are permitted
  2041. X * provided that the above copyright notice and this paragraph are
  2042. X * duplicated in all such forms and that any documentation,
  2043. X * advertising materials, and other materials related to such
  2044. X * distribution and use acknowledge that the software was developed
  2045. X * by Walter Tichy.
  2046. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  2047. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  2048. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  2049. X *
  2050. X * Report all problems and direct all questions to:
  2051. X *   rcs-bugs@@cs.purdue.edu
  2052. X * 
  2053. X
  2054. X
  2055. X
  2056. X
  2057. X
  2058. X
  2059. X
  2060. X*/
  2061. X
  2062. X
  2063. X
  2064. X
  2065. X/* $Log:    rlog.c,v $
  2066. X * Revision 4.7  89/05/01  15:13:48  narten
  2067. X * changed copyright header to reflect current distribution rules
  2068. X * 
  2069. X * Revision 4.6  88/11/08  11:59:40  narten
  2070. X * changes from  eggert@@sm.unisys.com (Paul Eggert)
  2071. X * 
  2072. X * Revision 4.6  88/08/09  19:13:28  eggert
  2073. X * Check for memory exhaustion; don't access freed storage.
  2074. X * Shrink stdio code size; remove lint.
  2075. X * 
  2076. X * Revision 4.5  87/12/18  11:46:38  narten
  2077. X * more lint cleanups (Guy Harris)
  2078. X * 
  2079. X * Revision 4.4  87/10/18  10:41:12  narten
  2080. X * Updating version numbers
  2081. X * Changes relative to 1.1 actually relative to 4.2
  2082. X * 
  2083. X * Revision 1.3  87/09/24  14:01:10  narten
  2084. X * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  2085. X * warnings)
  2086. X * 
  2087. X * Revision 1.2  87/03/27  14:22:45  jenkins
  2088. X * Port to suns
  2089. X * 
  2090. X * Revision 1.1  84/01/23  14:50:45  kcs
  2091. X * Initial revision
  2092. X * 
  2093. X * Revision 4.2  83/12/05  09:18:09  wft
  2094. X * changed rewriteflag to external.
  2095. X * 
  2096. X * Revision 4.1  83/05/11  16:16:55  wft
  2097. X * Added -b, updated getnumericrev() accordingly.
  2098. X * Replaced getpwuid() with getcaller().
  2099. X * 
  2100. X * Revision 3.7  83/05/11  14:24:13  wft
  2101. X * Added options -L and -R;
  2102. X * Fixed selection bug with -l on multiple files.
  2103. X * Fixed error on dates of the form -d'>date' (rewrote getdatepair()).
  2104. X * 
  2105. X * Revision 3.6  82/12/24  15:57:53  wft
  2106. X * shortened output format.
  2107. X *
  2108. X * Revision 3.5  82/12/08  21:45:26  wft
  2109. X * removed call to checkaccesslist(); used DATEFORM to format all dates;
  2110. X * removed unused variables.
  2111. X *
  2112. X * Revision 3.4  82/12/04  13:26:25  wft
  2113. X * Replaced getdelta() with gettree(); removed updating of field lockedby.
  2114. X *
  2115. X * Revision 3.3  82/12/03  14:08:20  wft
  2116. X * Replaced getlogin with getpwuid(), %02d with %.2d, fancydate with PRINTDATE.
  2117. X * Fixed printing of nil, removed printing of Suffix,
  2118. X * added shortcut if no revisions are printed, disambiguated struct members.
  2119. X *
  2120. X * Revision 3.2  82/10/18  21:09:06  wft
  2121. X * call to curdir replaced with getfullRCSname(),
  2122. X * fixed call to getlogin(), cosmetic changes on output,
  2123. X * changed conflicting long identifiers.
  2124. X *
  2125. X * Revision 3.1  82/10/13  16:07:56  wft
  2126. X * fixed type of variables receiving from getc() (char -> int).
  2127. X */
  2128. X
  2129. X
  2130. X
  2131. X#include "time.h"
  2132. X#include "rcsbase.h"
  2133. X#ifndef lint
  2134. Xstatic char rcsbaseid[] = RCSBASE;
  2135. X#endif
  2136. X
  2137. Xextern char * partialno();
  2138. Xextern char * getcaller();          /*get login of caller                   */
  2139. Xextern        free();
  2140. Xextern int    countnumflds();
  2141. Xextern int    compartial();
  2142. Xextern int    expandsym();          /*get numeric name of a revision        */
  2143. Xextern int nextc;                   /*next input character                  */
  2144. Xextern char Klog[];
  2145. Xextern char Ktext[];
  2146. Xextern int  partime();
  2147. Xextern long maketime();             /*convert parsed time to unix time.     */
  2148. Xextern struct tm * localtime();     /*convert unixtime into a tm-structure  */
  2149. Xextern int  pairfilenames();
  2150. Xextern struct hshentry  * getnum();
  2151. Xextern FILE * finptr;               /* RCS input file                       */
  2152. Xextern FILE * frewrite;             /* new RCS file                         */
  2153. Xextern int    rewriteflag;          /* indicates whether input should be    */
  2154. X                    /* echoed to frewrite */
  2155. Xextern int    nerror;               /* error counter                        */
  2156. X
  2157. Xchar * RCSfilename, * workfilename;
  2158. X
  2159. Xchar * caller;                        /* caller's login;                    */
  2160. Xint  descflag, selectflag, selectop;  /* option to print access list, symbolic  */
  2161. X                                      /* names, descriptive text, locks and */
  2162. X                                      /* Head                               */
  2163. Xint  onlylockflag;              /* option to print only files         */
  2164. X                      /* with locks                */
  2165. Xint  onlyRCSflag;                     /* option to print only RCS file name */
  2166. Xint  lockflag;                        /* whether locker option is set       */
  2167. Xint  revno;                           /* number of revision chosen          */
  2168. X
  2169. Xstruct  lockers {                     /* lockers in locker option; stored   */
  2170. X     char               * login;      /* lockerlist                         */
  2171. X     struct     lockers * lockerlink;
  2172. X     }  ;
  2173. X
  2174. Xstruct  stateattri {                  /* states in state option; stored in  */
  2175. X     char               * status;     /* statelist                          */
  2176. X     struct  stateattri * nextstate;
  2177. X     }  ;
  2178. X
  2179. Xstruct  authors {                     /* login names in author option;      */
  2180. X     char               * login;      /* stored in authorlist               */
  2181. X     struct     authors * nextauthor;
  2182. X     }  ;
  2183. X
  2184. Xstruct Revpairs{                      /* revision or branch range in -r     */
  2185. X     int                  numfld;     /* option; stored in revlist          */
  2186. X     char               * strtrev;
  2187. X     char               * endrev;
  2188. X     struct  Revpairs   * rnext;
  2189. X     } ;
  2190. X
  2191. Xstruct Datepairs{                     /* date range in -d option; stored in */
  2192. X     char               strtdate[datelength];   /* duelst and datelist      */
  2193. X     char               enddate[datelength];
  2194. X     struct  Datepairs  * dnext;
  2195. X     };
  2196. X
  2197. Xchar   Dotstring[200];                /* string of numeric revision name    */
  2198. Xchar   * Nextdotstring;               /* next available place of Dotstring  */
  2199. Xstruct  Datepairs       * datelist,  * duelst;
  2200. Xstruct  Revpairs        * revlist, * Revlst;
  2201. Xint                     branchflag; /* set on -b */
  2202. Xstruct  lockers         * lockerlist;
  2203. Xstruct  stateattri      * statelist;
  2204. Xstruct  authors         * authorlist;
  2205. X
  2206. X
  2207. X
  2208. Xmain (argc, argv)
  2209. Xint argc;
  2210. Xchar * argv[];
  2211. X{
  2212. X        struct  Datepairs       * currdate;
  2213. X        struct  assoc         * curassoc;
  2214. X        struct  access        * curaccess;
  2215. X        struct  lock          * currlock;
  2216. X        char * cmdusage;
  2217. X
  2218. X    cmdusage = "command format:\nrlog -L -R -h -t -b -ddates -l[lockers] -rrevisions -sstates -w[logins] file ...";
  2219. X        cmdid = "rlog";
  2220. X        descflag = selectflag = true;
  2221. X        lockflag = onlylockflag = selectop = false;
  2222. X    onlyRCSflag = false;
  2223. X        lockerlist = nil;
  2224. X        authorlist = nil;
  2225. X        statelist = nil;
  2226. X        Revlst = revlist = nil;
  2227. X        branchflag= false;
  2228. X        duelst = datelist = nil;
  2229. X    caller=getcaller();
  2230. X
  2231. X        while (--argc,++argv, argc>=1 && ((*argv)[0] == '-')) {
  2232. X                switch ((*argv)[1]) {
  2233. X
  2234. X        case 'L':
  2235. X            onlylockflag = true;
  2236. X            break;
  2237. X
  2238. X        case 'R':
  2239. X            onlyRCSflag =true;
  2240. X            break;
  2241. X
  2242. X                case 'l':
  2243. X                        selectop = true;
  2244. X                        lockflag = true;
  2245. X                        getlocker( (*argv)+2 );
  2246. X                        break;
  2247. X
  2248. X                case 'b':
  2249. X                        selectop = true;
  2250. X                        branchflag = true;
  2251. X                        break;
  2252. X
  2253. X                case 'r':
  2254. X                        selectop = true;
  2255. X                        getrevpairs( (*argv)+2 );
  2256. X                        break;
  2257. X
  2258. X                case 'd':
  2259. X                        selectop = true;
  2260. X                        getdatepair( (*argv)+2 );
  2261. X                        break;
  2262. X
  2263. X                case 's':
  2264. X                        selectop = true;
  2265. X                        getstate( (*argv)+2);
  2266. X                        break;
  2267. X
  2268. X                case 'w':
  2269. X                        selectop = true;
  2270. X                        getauthor( (*argv)+2);
  2271. X                        break;
  2272. X
  2273. X                case 'h':
  2274. X                        if ( ! selectflag ) warn("option -t overrides -h");
  2275. X                        else    descflag = false;
  2276. X                        break;
  2277. X
  2278. X                case 't':
  2279. X                        selectflag = false;
  2280. X                        if ( ! descflag ) warn("option -t overrides -h");
  2281. X                        descflag = true;
  2282. X                        break;
  2283. X
  2284. X                default:
  2285. X                        faterror("unknown option: %s\n%s", *argv,cmdusage);
  2286. X
  2287. X                };
  2288. X        } /* end of option processing */
  2289. X
  2290. X        if (argc<1) faterror("No input file\n%s",cmdusage);
  2291. X
  2292. X
  2293. X        /* now handle all filenames */
  2294. X        do {
  2295. X            rewriteflag=false;
  2296. X            finptr=frewrite=nil;
  2297. X
  2298. X
  2299. X            if (!pairfilenames(argc, argv, true,false)) continue;
  2300. X
  2301. X            /* now RCSfilename contains the name of the RCS file, and finptr
  2302. X             * the file descriptor. Workfilename contains the name of the
  2303. X             * working file.
  2304. X             */
  2305. X
  2306. X            if ( !trysema(RCSfilename, false)) goto loopend; /*  give up */
  2307. X
  2308. X            /* do nothing if -L is given and there are no locks*/
  2309. X        if ( onlylockflag && Locks == nil ) goto loopend;
  2310. X
  2311. X        if ( onlyRCSflag ) {
  2312. X        VOID fprintf(stdout, "%s\n", RCSfilename);
  2313. X        goto loopend;
  2314. X        }
  2315. X            /*   print RCS filename , working filename and optional
  2316. X                 administrative information                         */
  2317. X            VOID fprintf(stdout, "\nRCS file:        %s;   ",RCSfilename);
  2318. X            /* could use getfullRCSname() here, but that is very slow */
  2319. X            VOID fprintf(stdout, "Working file:    %s\n", workfilename);
  2320. X            VOID fprintf(stdout, "head:            %s\n", Head==nil?"":Head->num);
  2321. X            VOID fprintf(stdout, "branch:          %s\n", Dbranch==nil?"":Dbranch->num);
  2322. X
  2323. X            VOID fputs("locks:         ", stdout);  /*  print locker list   */
  2324. X            currlock = Locks;
  2325. X            while( currlock ) {
  2326. X                VOID fprintf(stdout,"  %s: %s;", currlock->login,
  2327. X                                currlock->delta->num);
  2328. X                currlock = currlock->nextlock;
  2329. X            }
  2330. X            if ( StrictLocks )
  2331. X                VOID fputs(Locks==nil?"  ;  strict":"  strict",stdout);
  2332. X
  2333. X            VOID fputs("\naccess list:   ", stdout);      /*  print access list  */
  2334. X            curaccess = AccessList;
  2335. X            while(curaccess) {
  2336. X                VOID fputs("  ",stdout);
  2337. X                VOID fputs(curaccess->login, stdout);
  2338. X                curaccess = curaccess->nextaccess;
  2339. X            }
  2340. X
  2341. X            VOID fputs("\nsymbolic names:", stdout);   /*  print symbolic names   */
  2342. X            curassoc = Symbols;
  2343. X            while( curassoc ) {
  2344. X                VOID fprintf(stdout, "  %s: %s;",curassoc->symbol,
  2345. X                           curassoc->delta->num);
  2346. X                curassoc = curassoc->nextassoc;
  2347. X            }
  2348. X
  2349. X            VOID fprintf(stdout,"\ncomment leader:  \"%s\"\n",Comment);
  2350. X
  2351. X            gettree();
  2352. X            VOID fprintf(stdout, "total revisions: %d;    ", TotalDeltas);
  2353. X            if ( Head == nil || !selectflag || !descflag) {
  2354. X                VOID putc('\n',stdout);
  2355. X                if (descflag) VOID fputs("description:\n", stdout);
  2356. X                getdesc(descflag);
  2357. X                VOID fputs("=============================================================================\n",stdout);
  2358. X                goto loopend;
  2359. X            }
  2360. X
  2361. X
  2362. X            /*  keep only those locks given by -l */
  2363. X            if (lockflag)
  2364. X                trunclocks();
  2365. X            getnumericrev();    /* get numeric revision or branch names */
  2366. X            revno = 0;
  2367. X
  2368. X            exttree(Head);
  2369. X
  2370. X            /*  get most recently date of the dates pointed by duelst  */
  2371. X            currdate = duelst;
  2372. X            while( currdate) {
  2373. X                recentdate(Head, currdate);
  2374. X                currdate = currdate->dnext;
  2375. X        }
  2376. X
  2377. X            extdate(Head);
  2378. X
  2379. X            /*  reinitialize the date specification list   */
  2380. X            currdate = duelst;
  2381. X            while(currdate) {
  2382. X                VOID sprintf(currdate->strtdate,DATEFORM,0,0,0,0,0,0);
  2383. X                currdate = currdate->dnext;
  2384. X            }
  2385. X
  2386. X            if ( selectop || ( selectflag && descflag) )
  2387. X                VOID fprintf(stdout, "selected revisions: %d", revno);
  2388. X            VOID putc('\n', stdout);
  2389. X            if (descflag) VOID fputs("description:\n", stdout);
  2390. X            getdesc(descflag);
  2391. X            while( (nexttok != EOFILE) && readdeltalog());
  2392. X            if (selectflag && descflag && revno) {
  2393. X                putrunk();
  2394. X                putree(Head);
  2395. X                if (nextlex(), nexttok != EOFILE)
  2396. X                    fatserror("syntax error; expecting EOF");
  2397. X            }
  2398. X            VOID fputs("=============================================================================\n",stdout);
  2399. X        loopend:
  2400. X            VOID fclose(finptr);
  2401. X        } while( ++argv, --argc >= 1);
  2402. X        exit(nerror!=0);
  2403. X}
  2404. X
  2405. X
  2406. X
  2407. Xputrunk()
  2408. X/*  function:  print revisions chosen, which are in trunk      */
  2409. X
  2410. X{
  2411. X        struct  hshentry        * ptr, * pre;
  2412. X
  2413. X        if (Head == nil) return;   /*  empty tree  */
  2414. X
  2415. X        pre = Head;
  2416. X        ptr = Head->next;
  2417. X        while( ptr ) {
  2418. X            putadelta(pre,ptr,true);
  2419. X            pre = ptr;
  2420. X            ptr = ptr->next;
  2421. X        }
  2422. X        putadelta(pre,ptr,true);
  2423. X}
  2424. X
  2425. X
  2426. X
  2427. Xputree(root)
  2428. Xstruct  hshentry  *root;
  2429. X/*   function: print delta tree( not include trunck) in reversed calender
  2430. X               order on each branch                                        */
  2431. X
  2432. X{
  2433. X        if ( root == nil ) return;
  2434. X
  2435. X        putree(root->next);
  2436. X
  2437. X        putforest(root->branches);
  2438. X}
  2439. X
  2440. X
  2441. X
  2442. X
  2443. Xputforest(branchroot)
  2444. Xstruct   branchhead     * branchroot;
  2445. X/*   function:  print branches that has the same direct ancestor    */
  2446. X{
  2447. X
  2448. X        if ( branchroot == nil ) return;
  2449. X
  2450. X        putforest(branchroot->nextbranch);
  2451. X
  2452. X        putabranch(branchroot->hsh);
  2453. X        putree(branchroot->hsh);
  2454. X}
  2455. X
  2456. X
  2457. X
  2458. X
  2459. Xputabranch(root)
  2460. Xstruct      hshentry   *root;
  2461. X/*   function  :  print one branch     */
  2462. X
  2463. X{
  2464. X
  2465. X        if ( root == nil) return;
  2466. X
  2467. X        putabranch(root->next);
  2468. X
  2469. X        putadelta(root, root, false);
  2470. X}
  2471. X
  2472. X
  2473. X
  2474. X
  2475. X
  2476. Xputadelta(node,editscript,trunk)
  2477. Xregister  struct   hshentry    * node;
  2478. Xregister  struct   hshentry    * editscript;
  2479. Xint                              trunk;
  2480. X/*  function: print delta node if node->selector is 's'.        */
  2481. X/*      editscript indicates where the editscript is stored     */
  2482. X/*      trunk indicated whether this node is in trunk           */
  2483. X{
  2484. X        struct  branchhead      * newbranch;
  2485. X        char                    * branchnum,  branch[40];
  2486. X
  2487. X        if ( ( node == nil) || ( node->selector == 'u'))
  2488. X            return;
  2489. X
  2490. X        VOID fprintf(stdout,"----------------------------\n");
  2491. X        VOID fprintf(stdout, "revision %s        ",node->num);
  2492. X        if ( node->lockedby )
  2493. X           VOID fprintf(stdout, "locked by: %s;       ", node->lockedby);
  2494. X        VOID putc('\n', stdout);
  2495. X
  2496. X        VOID fputs("date: ",stdout);
  2497. X        VOID PRINTDATE(stdout,node->date); VOID putc(' ',stdout);
  2498. X        VOID PRINTTIME(stdout,node->date);
  2499. X        VOID fprintf(stdout, ";  author: %s;  ", node->author);
  2500. X        VOID fprintf(stdout, "state: %s;  ", node->state);
  2501. X
  2502. X        if ( editscript )
  2503. X           if(trunk)
  2504. X              VOID fprintf(stdout,"lines added/del: %d/%d",
  2505. X                             editscript->deletelns, editscript->insertlns);
  2506. X           else
  2507. X              VOID fprintf(stdout,"lines added/del: %d/%d",
  2508. X                             editscript->insertlns, editscript->deletelns);
  2509. X
  2510. X        VOID putc('\n', stdout);
  2511. X
  2512. X        branchnum = & (branch[0]);
  2513. X        newbranch = node->branches;
  2514. X        if ( newbranch ) {
  2515. X           VOID fputs("branches:  ", stdout);
  2516. X           while( newbranch ) {
  2517. X                getbranchno(newbranch->hsh->num, branchnum);
  2518. X                VOID fprintf(stdout, "%s;  ", branchnum);
  2519. X                newbranch = newbranch->nextbranch;
  2520. X           }
  2521. X           VOID putc('\n', stdout);
  2522. X        }
  2523. X
  2524. X        VOID fputs(node->log,stdout);
  2525. X}
  2526. X
  2527. X
  2528. X
  2529. X
  2530. X
  2531. Xreaddeltalog()
  2532. X/*  Function : get the log message and skip the text of a deltatext node.
  2533. X *             Return false if current block does not start with a number.
  2534. X *             Assumes the current lexeme is not yet in nexttok; does not
  2535. X *             advance nexttok.
  2536. X */
  2537. X{
  2538. X        register struct  hshentry  * Delta;
  2539. X
  2540. X        nextlex();
  2541. X        if ( !(Delta = getnum() )) return(false);
  2542. X        if ( ! getkey(Klog) || ( nexttok != STRING ) )
  2543. X                fatserror("Missing log entry");
  2544. X        Delta->log = talloc(logsize);
  2545. X        VOID savestring(Delta->log, logsize);
  2546. X        nextlex();
  2547. X        if ( ! getkey(Ktext) || (nexttok != STRING) )
  2548. X                fatserror("Missing delta text");
  2549. X        Delta->insertlns = Delta->deletelns = 0;
  2550. X        if ( Delta != Head)
  2551. X                getscript(Delta);
  2552. X        else
  2553. X                readstring();
  2554. X        return true;
  2555. X}
  2556. X
  2557. X
  2558. X
  2559. Xgetscript(Delta)
  2560. Xstruct    hshentry   * Delta;
  2561. X/*   function:  read edit script of Delta and count how many lines added  */
  2562. X/*              and deleted in the script                                 */
  2563. X
  2564. X{
  2565. X        int ed;   /*  editor command  */
  2566. X    register FILE * fin;
  2567. X        register  int   c;
  2568. X        register  int   i;
  2569. X        int             length;
  2570. X
  2571. X    fin = finptr;
  2572. X    while( (ed = getc(fin)) != EOF) {
  2573. X           /*  assume first none white character is command name  */
  2574. X            while( ed == '\n' || ed == ' ' || ed == '\t')
  2575. X        ed = getc(fin);
  2576. X            if (ed == SDELIM) break;  /*  script text is ended   */
  2577. X        while( ( c = getc(fin)) == ' ' );  /*  skip blank  */
  2578. X            if ( ! ('0' <= c && c <= '9')) {
  2579. X                faterror("Missing line number in edit script");
  2580. X                break;
  2581. X            }
  2582. X        while( '0' <= (c = getc(fin)) && c <= '9' ) ;
  2583. X
  2584. X        while( c == ' ')c = getc(fin);  /*  skip blanks  */
  2585. X            if ( !('0' <= c && c <= '9' ) ) {
  2586. X                faterror("Incorrect range in edit script");
  2587. X                break;
  2588. X            }
  2589. X            length = c - '0';
  2590. X        while( '0' <= (c = getc(fin)) && c <= '9' )
  2591. X                length = length * 10 + c - '0';
  2592. X        while( c != '\n' && c != EOF) c = getc(fin);
  2593. X            switch (ed) {
  2594. X            case 'd' :
  2595. X                 Delta->deletelns += length;
  2596. X                 break;
  2597. X
  2598. X            case 'a' :
  2599. X                 /*  skip scripted lines  */
  2600. X                 for ( i=length; i > 0 && c != EOF; i--){
  2601. X             while( (c=getc(fin)) != '\n' && c != EOF);
  2602. X                     Delta->insertlns++;
  2603. X                 }
  2604. X                 break;
  2605. X
  2606. X            default:
  2607. X                 faterror("Unknown command in edit script: %c", ed);
  2608. X                 break;
  2609. X            }
  2610. X        }
  2611. X    nextc = getc(fin);
  2612. X}
  2613. X
  2614. X
  2615. X
  2616. X
  2617. X
  2618. X
  2619. X
  2620. Xexttree(root)
  2621. Xstruct hshentry  *root;
  2622. X/*  function: select revisions , starting with root             */
  2623. X
  2624. X{
  2625. X        struct branchhead       * newbranch;
  2626. X
  2627. X        if (root == nil) return;
  2628. X
  2629. X        extractdelta(root);
  2630. X        exttree(root->next);
  2631. X
  2632. X        newbranch = root->branches;
  2633. X        while( newbranch ) {
  2634. X            exttree(newbranch->hsh);
  2635. X            newbranch = newbranch->nextbranch;
  2636. X        }
  2637. X}
  2638. X
  2639. X
  2640. X
  2641. X
  2642. Xgetlocker(argv)
  2643. Xchar    * argv;
  2644. X/*   function : get the login names of lockers from command line   */
  2645. X/*              and store in lockerlist.                           */
  2646. X
  2647. X{
  2648. X        register char c;
  2649. X        struct   lockers   * newlocker;
  2650. X        argv--;
  2651. X        while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
  2652. X                 c == '\n' || c == ';')  ;
  2653. X        if (  c == '\0') {
  2654. X            lockerlist=nil;
  2655. X            return;
  2656. X        }
  2657. X
  2658. X        while( c != '\0' ) {
  2659. X            newlocker = ( struct lockers *)talloc( sizeof(struct lockers) );
  2660. X            newlocker->lockerlink = lockerlist;
  2661. X            newlocker->login = argv;
  2662. X            lockerlist = newlocker;
  2663. X            while ( ( c = (*++argv)) != ',' && c != '\0' && c != ' '
  2664. X                       && c != '\t' && c != '\n' && c != ';') ;
  2665. X            *argv = '\0';
  2666. X            if ( c == '\0' ) return;
  2667. X            while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
  2668. X                     c == '\n' || c == ';')  ;
  2669. X        }
  2670. X}
  2671. X
  2672. X
  2673. X
  2674. Xgetauthor(argv)
  2675. Xchar   *argv;
  2676. X/*   function:  get the author's name form command line   */
  2677. X/*              and store in aauthorlist                  */
  2678. X
  2679. X{
  2680. X        register    c;
  2681. X        struct     authors  * newauthor;
  2682. X
  2683. X        argv--;
  2684. X        while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
  2685. X                 c == '\n' || c == ';')  ;
  2686. X        if ( c == '\0' ) {
  2687. X            authorlist = (struct authors *)talloc(sizeof(struct authors));
  2688. X            authorlist->login = caller;
  2689. X            authorlist->nextauthor  = nil;
  2690. X            return;
  2691. X        }
  2692. X
  2693. X        while( c != '\0' ) {
  2694. X            newauthor = (struct authors *)talloc(sizeof(struct authors));
  2695. X            newauthor->nextauthor = authorlist;
  2696. X            newauthor->login = argv;
  2697. X            authorlist = newauthor;
  2698. X            while( ( c = *++argv) != ',' && c != '\0' && c != ' '
  2699. X                     && c != '\t' && c != '\n' && c != ';') ;
  2700. X            * argv = '\0';
  2701. X            if ( c == '\0') return;
  2702. X            while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
  2703. X                     c == '\n' || c == ';')  ;
  2704. X        }
  2705. X}
  2706. X
  2707. X
  2708. X
  2709. X
  2710. Xgetstate(argv)
  2711. Xchar   * argv;
  2712. X/*   function :  get the states of revisions from command line  */
  2713. X/*               and store in statelist                         */
  2714. X
  2715. X{
  2716. X        register  char  c;
  2717. X        struct    stateattri    *newstate;
  2718. X
  2719. X        argv--;
  2720. X        while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
  2721. X                 c == '\n' || c == ';')  ;
  2722. X        if ( c == '\0'){
  2723. X            warn(" Missing state attributes after -s options");
  2724. X            return;
  2725. X        }
  2726. X
  2727. X        while( c != '\0' ) {
  2728. X            newstate = (struct stateattri *)talloc(sizeof(struct stateattri));
  2729. X            newstate->nextstate = statelist;
  2730. X            newstate->status = argv;
  2731. X            statelist = newstate;
  2732. X            while( (c = (*++argv)) != ',' && c != '\0' && c != ' '
  2733. X                    && c != '\t' && c != '\n' && c != ';')  ;
  2734. X            *argv = '\0';
  2735. X            if ( c == '\0' ) return;
  2736. X            while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
  2737. X                     c == '\n' || c == ';')  ;
  2738. X        }
  2739. X}
  2740. X
  2741. X
  2742. X
  2743. Xtrunclocks()
  2744. X/*  Function:  Truncate the list of locks to those that are held by the  */
  2745. X/*             id's on lockerlist. Do not truncate if lockerlist empty.  */
  2746. X
  2747. X{
  2748. X        struct lockers  * plocker;
  2749. X        struct lock     * plocked,  * nextlocked;
  2750. X
  2751. X        if ( (lockerlist == nil) || (Locks == nil)) return;
  2752. X
  2753. X        /* shorten Locks to those contained in lockerlist */
  2754. X        plocked = Locks;
  2755. X        Locks = nil;
  2756. X        while( plocked != nil) {
  2757. X            plocker = lockerlist;
  2758. X            while((plocker != nil) && ( strcmp(plocker->login, plocked->login)!=0))
  2759. X                plocker = plocker->lockerlink;
  2760. X            nextlocked = plocked->nextlock;
  2761. X            if ( plocker != nil) {
  2762. X                plocked->nextlock = Locks;
  2763. X                Locks = plocked;
  2764. X            }
  2765. X            plocked = nextlocked;
  2766. X        }
  2767. X}
  2768. X
  2769. X
  2770. X
  2771. Xrecentdate(root, pd)
  2772. Xstruct     hshentry    * root;
  2773. Xstruct    Datepairs    * pd;
  2774. X/*  function:  Finds the delta that is closest to the cutoff date given by   */
  2775. X/*             pd among the revisions selected by exttree.                   */
  2776. X/*             Successively narrows down the interfal given by pd,           */
  2777. X/*             and sets the strtdate of pd to the date of the selected delta */
  2778. X{
  2779. X        struct  branchhead      * newbranch;
  2780. X
  2781. X    if ( root == nil) return;
  2782. X        if ( root->selector == 's') {
  2783. X             if ( cmpnum(root->date, pd->strtdate) >= 0 &&
  2784. X                  cmpnum(root->date, pd->enddate) <= 0)
  2785. X        VOID strcpy(pd->strtdate, root->date);
  2786. X        }
  2787. X
  2788. X        recentdate(root->next, pd);
  2789. X        newbranch = root->branches;
  2790. X        while( newbranch) {
  2791. X           recentdate(newbranch->hsh, pd);
  2792. X           newbranch = newbranch->nextbranch;
  2793. X    }
  2794. X}
  2795. X
  2796. X
  2797. X
  2798. X
  2799. X
  2800. X
  2801. Xextdate(root)
  2802. Xstruct  hshentry        * root;
  2803. X/*  function:  select revisions which are in the date range specified     */
  2804. X/*             in duelst  and datelist, start at root                     */
  2805. X
  2806. X{
  2807. X        struct  branchhead      * newbranch;
  2808. X        struct  Datepairs       * pdate;
  2809. X
  2810. X        if ( root == nil) return;
  2811. X
  2812. X        if ( datelist || duelst) {
  2813. X            pdate = datelist;
  2814. X            while( pdate ) {
  2815. X                if ( (pdate->strtdate)[0] == '\0' || cmpnum(root->date,pdate->strtdate) >= 0){
  2816. X                   if ((pdate->enddate)[0] == '\0' || cmpnum(pdate->enddate,root->date) >= 0)
  2817. X                        break;
  2818. X                }
  2819. X                pdate = pdate->dnext;
  2820. X            }
  2821. X            if ( pdate == nil) {
  2822. X                pdate = duelst;
  2823. X                while(pdate) {
  2824. X                   if ( cmpnum(root->date, pdate->strtdate) == 0)
  2825. X                      break;
  2826. X                   pdate = pdate->dnext;
  2827. X                }
  2828. X            }
  2829. X            if ( pdate == nil)
  2830. X                root->selector = 'u';
  2831. X        }
  2832. X        if (root->selector == 's') revno++;
  2833. X
  2834. X        extdate(root->next);
  2835. X
  2836. X        newbranch = root->branches;
  2837. X        while( newbranch ) {
  2838. X           extdate(newbranch->hsh);
  2839. X           newbranch = newbranch->nextbranch;
  2840. X        }
  2841. X}
  2842. X
  2843. X
  2844. X
  2845. Xextractdelta(pdelta)
  2846. Xstruct  hshentry        * pdelta;
  2847. X/*  function:  compare information of pdelta to the authorlst, lockerlist, */
  2848. X/*             statelist, revlist and mark 's' on selector if pdelta is    */
  2849. X/*             selected; otherwise, mark 'u'                               */
  2850. X
  2851. X{
  2852. X        struct  lock            * plock;
  2853. X        struct  stateattri      * pstate;
  2854. X        struct  authors         * pauthor;
  2855. X        struct  Revpairs        * prevision;
  2856. X        int                       length;
  2857. X
  2858. X        pdelta->selector = 's';
  2859. X        if ( authorlist ) {  /*  certain author's revisions wanted only  */
  2860. X            pauthor = authorlist;
  2861. X            while((pauthor != nil) && ( strcmp(pauthor->login, pdelta->author)!=0))
  2862. X                pauthor = pauthor->nextauthor;
  2863. X            if ( pauthor == nil ) {
  2864. X                pdelta->selector = 'u';
  2865. X                return;
  2866. X            }
  2867. X        }
  2868. X        if ( statelist ) {   /* revisions with certain state wanted  */
  2869. X            pstate = statelist;
  2870. X            while((pstate != nil) && (strcmp(pstate->status, pdelta->state)!=0))
  2871. X                pstate = pstate->nextstate;
  2872. X            if ( pstate == nil ) {
  2873. X                pdelta->selector = 'u';
  2874. X                return;
  2875. X            }
  2876. X        }
  2877. X        if ( lockflag ) {    /*  locked revisions   */
  2878. X            plock = Locks;
  2879. X            while( plock && (plock->delta != pdelta))
  2880. X                plock = plock->nextlock;
  2881. X            if (plock == nil ) {
  2882. X                pdelta->selector = 'u';
  2883. X                return;
  2884. X            }
  2885. X        }
  2886. X        if ( Revlst ) {   /*  revisions or branches selected  */
  2887. X
  2888. X            prevision = Revlst;
  2889. X            while( prevision != nil ) {
  2890. X                length = prevision->numfld;
  2891. X                if ( length % 2 == 1) { /*  a branch number  */
  2892. X                     if ( countnumflds(pdelta->num) ==(length+1))
  2893. X                        if ( (compartial(pdelta->num, prevision->strtrev,length) >= 0)&&
  2894. X                             (compartial(prevision->endrev, pdelta->num, length) >= 0) )
  2895. X                             break;
  2896. X                }
  2897. X                else if ( countnumflds(pdelta->num ) == length)  /*  a revision */
  2898. X                    if ( (compartial(pdelta->num, prevision->strtrev, length) >= 0) &&
  2899. X                         (compartial(prevision->endrev, pdelta->num, length) >= 0) )
  2900. X                        break;
  2901. X                prevision = prevision->rnext;
  2902. X            }
  2903. X            if (prevision == nil)  {
  2904. X                pdelta->selector = 'u';
  2905. X                return;
  2906. X            }
  2907. X        }
  2908. X}
  2909. X
  2910. X
  2911. X
  2912. Xchar * procdate(target, source)
  2913. Xchar * target, * source;
  2914. X/* Function: Parses a free-format date in target, converts it
  2915. X * into RCS internal format, and stores the result into source.
  2916. X * Returns target on success, nil otherwise.
  2917. X */
  2918. X{
  2919. X    long            unixtime;
  2920. X    struct     tm   parseddate,  *ftm;
  2921. X
  2922. X    if ( partime(source, &parseddate) == 0) {
  2923. X        error("Can't parse date/time: %s", source);
  2924. X        *target= '\0';
  2925. X        return nil;
  2926. X    }
  2927. X    if ( (unixtime = maketime(&parseddate)) == 0L) {
  2928. X        error("Inconsistent date/time: %s", source);
  2929. X        *target='\0';
  2930. X        return nil;
  2931. X    }
  2932. X    ftm = localtime(&unixtime);
  2933. X    VOID sprintf(target,DATEFORM,
  2934. X    ftm->tm_year,ftm->tm_mon+1,ftm->tm_mday,ftm->tm_hour,ftm->tm_min,ftm->tm_sec);
  2935. X    return target;
  2936. X}
  2937. X
  2938. X
  2939. X
  2940. Xgetdatepair(argv)
  2941. X   char   * argv;
  2942. X/*  function:  get time range from command line and store in datelist if    */
  2943. X/*             a time range specified or in duelst if a time spot specified */
  2944. X
  2945. X{
  2946. X        register   char         c;
  2947. X        struct     Datepairs    * nextdate;
  2948. X        char                    * rawdate;
  2949. X    int                     switchflag;
  2950. X
  2951. X        argv--;
  2952. X        while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
  2953. X                 c == '\n' || c == ';')  ;
  2954. X        if ( c == '\0' ) {
  2955. X            warn("Missing date/time after -d");
  2956. X            return;
  2957. X        }
  2958. X
  2959. X        while( c != '\0' )  {
  2960. X        switchflag = false;
  2961. X        nextdate = (struct Datepairs *) talloc(sizeof(struct Datepairs));
  2962. X            if ( c == '<' ) {   /*   case: -d <date   */
  2963. X                c = *++argv;
  2964. X                (nextdate->strtdate)[0] = '\0';
  2965. X        } elsif (c == '>') {        /*  case:  -d >date     */
  2966. X        c = *++argv;
  2967. X        (nextdate->enddate)[0] = '\0';
  2968. X        switchflag = true;
  2969. X        } else {
  2970. X                rawdate = argv;
  2971. X        while( c != '<' && c != '>' && c != ';' && c != '\0')
  2972. X             c = *++argv;
  2973. X                *argv = '\0';
  2974. X        if ( c == '>' ) switchflag=true;
  2975. X        if (procdate(switchflag?nextdate->enddate:nextdate->strtdate,
  2976. X                 rawdate)==nil) continue;
  2977. X        if ( c == ';' || c == '\0') {  /*  case: -d date  */
  2978. X            VOID strcpy(nextdate->enddate,nextdate->strtdate);
  2979. X            VOID sprintf(nextdate->strtdate,DATEFORM,0,0,0,0,0,0);
  2980. X                    nextdate->dnext = duelst;
  2981. X                    duelst = nextdate;
  2982. X            goto end;
  2983. X        } else {
  2984. X            /*   case:   -d date<  or -d  date>; see switchflag */
  2985. X            while ( (c= *++argv) == ' ' || c=='\t' || c=='\n');
  2986. X            if ( c == ';' || c == '\0') {
  2987. X            /* second date missing */
  2988. X            if (switchflag)
  2989. X                *nextdate->strtdate= '\0';
  2990. X            else
  2991. X                *nextdate->enddate= '\0';
  2992. X            nextdate->dnext = datelist;
  2993. X            datelist = nextdate;
  2994. X            goto end;
  2995. X            }
  2996. X                }
  2997. X            }
  2998. X            rawdate = argv;
  2999. X        while( c != '>' && c != '<' && c != ';' && c != '\0')
  3000. X         c = *++argv;
  3001. X            *argv = '\0';
  3002. X        if (procdate(switchflag?nextdate->strtdate:nextdate->enddate,
  3003. X             rawdate)==nil) continue;
  3004. X            nextdate->dnext = datelist;
  3005. X        datelist = nextdate;
  3006. X     end:
  3007. X/*
  3008. X        VOID printf("startdate: %s; enddate: %s;\n", nextdate->strtdate,nextdate->enddate);
  3009. X*/
  3010. X        if ( c == '\0')  return;
  3011. X            while( (c = *++argv) == ';' || c == ' ' || c == '\t' || c =='\n');
  3012. X        }
  3013. X}
  3014. X
  3015. X
  3016. X
  3017. X
  3018. X
  3019. Xgetnumericrev()
  3020. X/*  function:  get the numeric name of revisions which stored in revlist  */
  3021. X/*             and then stored the numeric names in Revlst                */
  3022. X/*             if branchflag, also add default branch                     */
  3023. X
  3024. X{
  3025. X        struct  Revpairs        * ptr, *pt;
  3026. X        int     flag;
  3027. X        char    *temprev;
  3028. X
  3029. X        /*  free the previous numeric revision list  */
  3030. X        pt = Revlst;
  3031. X        while( pt) {
  3032. X       ptr = pt->rnext;
  3033. X           free((char *)pt);
  3034. X           pt = ptr;
  3035. X        }
  3036. X        Nextdotstring = &Dotstring[0]; /* reset buffer */
  3037. X
  3038. X
  3039. X        Revlst = nil;
  3040. X        ptr = revlist;
  3041. X        while( ptr ) {
  3042. X            pt = (struct Revpairs *) talloc(sizeof(struct Revpairs));
  3043. X            if ( ptr->numfld == 1 ){ /*  case:  -r rev   */
  3044. X                if ( (flag = expandsym(ptr->strtrev, Nextdotstring)) == true ) {
  3045. X                    pt->numfld = countnumflds(Nextdotstring);
  3046. X                    pt->strtrev = pt->endrev = Nextdotstring;
  3047. X                    while( *Nextdotstring++ != '\0' )  ;
  3048. X                }
  3049. X            }
  3050. X            else if( ptr->numfld == 2){ /*  case: -r rev-   */
  3051. X                if ( (flag = expandsym(ptr->strtrev, Nextdotstring)) == true) {
  3052. X                    pt->numfld = countnumflds(Nextdotstring);
  3053. X                    pt->strtrev = Nextdotstring;
  3054. X                    while( *Nextdotstring++ != '\0' ) ;
  3055. X                    pt->endrev = Nextdotstring;
  3056. X                    if ( pt->numfld > 2) choptail(pt->strtrev);
  3057. X                    * Nextdotstring++ = '\0';
  3058. X                }
  3059. X             }
  3060. X             else if(ptr->numfld == 3)  { /*  case: -r -rev   */
  3061. X                if ( (flag = expandsym(ptr->endrev, Nextdotstring)) == true) {
  3062. X                    pt->endrev = Nextdotstring;
  3063. X                    while( *Nextdotstring++ != '\0' )  ;
  3064. X                    pt->numfld = countnumflds(pt->endrev);
  3065. X                    pt->strtrev = Nextdotstring;
  3066. X                    if ( pt->numfld == 2)
  3067. X                        *Nextdotstring++ = '1';
  3068. X                    else
  3069. X                        choptail(pt->endrev);
  3070. X                    *Nextdotstring++ = '.';
  3071. X                    *Nextdotstring++ = '1';
  3072. X                    *Nextdotstring++ = '\0';
  3073. X                }
  3074. X             }
  3075. X             else  {     /*   case:  -r rev1-rev2   */
  3076. X                if ( (flag = expandsym(ptr->strtrev, Nextdotstring)) == true ) {
  3077. X                    pt->strtrev = Nextdotstring;
  3078. X                    while( *Nextdotstring++ != '\0' )  ;
  3079. X                    if ( ( flag = expandsym(ptr->endrev, Nextdotstring)) == true)  {
  3080. X                        pt->numfld = countnumflds(pt->strtrev);
  3081. X                        pt->endrev = Nextdotstring;
  3082. X                        while( *Nextdotstring++ != '\0' ) ;
  3083. X                        if((flag = checkrevpair(pt->strtrev, pt->endrev)) == true)
  3084. X                           /*  switch pt->strtrev with pt->endrev, if pt->strtrev > pt->endre  */
  3085. X                            if (compartial(pt->strtrev, pt->endrev, pt->numfld) > 0 ) {
  3086. X                                temprev = pt->strtrev;
  3087. X                                pt->strtrev = pt->endrev;
  3088. X                                pt->endrev = temprev;
  3089. X                            }
  3090. X                     }
  3091. X                }
  3092. X             }
  3093. X
  3094. X             if ( flag ){
  3095. X                pt->rnext = Revlst;
  3096. X                Revlst = pt;
  3097. X             }
  3098. X             else
  3099. X                free((char *)pt);
  3100. X             ptr = ptr->rnext;
  3101. X        }
  3102. X        /* Now take care of branchflag */
  3103. X        if (branchflag) {
  3104. X            flag =true;
  3105. X            pt = (struct Revpairs *) talloc(sizeof(struct Revpairs));
  3106. X            if (Dbranch) {
  3107. X                pt->strtrev = pt->endrev = Dbranch->num;
  3108. X            } elsif (Head!=nil) {
  3109. X                pt->strtrev = pt->endrev = /* branch number of head */
  3110. X                    partialno(Nextdotstring,Head->num,1);
  3111. X                while( *Nextdotstring++ != '\0' ) ;
  3112. X            } else flag = false;
  3113. X            if (flag) { /* prepend new node */
  3114. X                pt->rnext=Revlst; Revlst=pt;
  3115. X                pt->numfld = countnumflds(pt->strtrev);
  3116. X            }
  3117. X        }
  3118. X
  3119. X}
  3120. X
  3121. X
  3122. X
  3123. Xcheckrevpair(num1,num2)
  3124. Xchar    *num1,  *num2;
  3125. X/*  function:  check whether num1, num2 are legal pair,i.e.
  3126. X    only the last field are different and have same number of
  3127. X    feilds( if length <= 2, may be different if first field)   */
  3128. X
  3129. X{
  3130. X        int    length;
  3131. X
  3132. X        if ( (length = countnumflds(num1)) != countnumflds(num2) ) {
  3133. X            error(" Invalid branch or revision pair %s : %s", num1, num2);
  3134. X            return false;
  3135. X        }
  3136. X        if ( length > 2 )
  3137. X            if (compartial(num1, num2, length-1) != 0) {
  3138. X                error("Invalid branch or revision pair %s : %s", num1, num2);
  3139. X                return false;
  3140. X            }
  3141. X
  3142. X        return true;
  3143. X}
  3144. X
  3145. X
  3146. X
  3147. Xgetrevpairs(argv)
  3148. Xregister     char    * argv;
  3149. X/*  function:  get revision or branch range from command line, and   */
  3150. X/*             store in revlist                                      */
  3151. X
  3152. X{
  3153. X        register    char    c;
  3154. X        struct      Revpairs  * nextrevpair;
  3155. X        int         flag;
  3156. X
  3157. X        argv--;
  3158. X        while( ( c = (*++argv)) == ',' || c == ' ' || c == '\t' ||
  3159. X                 c == '\n' || c == ';')  ;
  3160. X        if ( c == '\0' ) {
  3161. X            warn(" Missing revision or branch number after -r");
  3162. X            return;
  3163. X        }
  3164. X
  3165. X        while( c != '\0') {
  3166. X            while(  c  == ',' || c == ' ' || c == '\t' ||
  3167. X                     c == '\n' || c == ';') c = *++argv;
  3168. X            if (c == '\0')  return;
  3169. X            nextrevpair = (struct Revpairs *) talloc(sizeof(struct Revpairs));
  3170. X            nextrevpair->rnext = revlist;
  3171. X            revlist = nextrevpair;
  3172. X            nextrevpair->numfld  = nil;
  3173. X            nextrevpair->strtrev = nil;
  3174. X            nextrevpair->endrev  = nil;
  3175. X            flag = false;
  3176. X            if (  c == '<' || c == '-' ) {  /*  case: -r -rev  or -r <rev  */
  3177. X                flag = true;
  3178. X                while( (c =(*++argv)) == ' ' || c == '\t' || c =='\n') ;
  3179. X            }
  3180. X            else {
  3181. X                nextrevpair->strtrev = argv;
  3182. X                /*   get a revision or branch name  */
  3183. X                while( c != ',' && c != ';' && c != ' ' && c != '\0' && c != '-'
  3184. X                        && c != '\t' && c != '\n' && c != '<') c = *++argv;
  3185. X
  3186. X                *argv = '\0';
  3187. X
  3188. X                if ( c != '<' && c != '-') {    /*  case: rev  */
  3189. X                    nextrevpair->numfld = 1;
  3190. X                    continue;
  3191. X                }
  3192. X
  3193. X                if ( (c =(*++argv)) == ',' || c == '\0' || c == ' '
  3194. X                      || c == '\t' || c == '\n' || c == ';') {/*  case: rev_  */
  3195. X                    nextrevpair->numfld = 2;
  3196. X                    continue;
  3197. X                }
  3198. X            }
  3199. X            nextrevpair->endrev = argv;
  3200. X            while( c != ',' && c != ' ' && c != '\0' && c != '\t' && c != '<'
  3201. X                   && c != '\n' && c != '-' && c != ';')  c = *++argv;
  3202. X
  3203. X            * argv = '\0';
  3204. X            if ( c == '<'){
  3205. X                error("separator expected near %s", nextrevpair->endrev);
  3206. X                while( (c = *++argv) != ',' && c != ' ' && c != '\0' &&
  3207. X                        c != '\t' && c != '\n' && c != ';' ) ;
  3208. X                revlist = nextrevpair->rnext;
  3209. X                continue;
  3210. X            }
  3211. X            else  {
  3212. X                if (flag)   /*  case:  -rev   */
  3213. X                    nextrevpair->numfld  = 3;
  3214. X
  3215. X                else     /*   rev1-rev2  appears  */
  3216. X                    nextrevpair->numfld = 4;
  3217. X            }
  3218. X        }
  3219. X}
  3220. X
  3221. X
  3222. X
  3223. Xchoptail(strhead)
  3224. Xchar     * strhead;
  3225. X/*   function : chop off the last field of a branch or a revision number  */
  3226. X
  3227. X{
  3228. X        char    *pt, *sp;
  3229. X
  3230. X        for(pt = Nextdotstring-1; pt != strhead && *pt != '.'; pt--) ;
  3231. X        for(sp = strhead; sp < pt; sp++) *Nextdotstring++ = *sp;
  3232. X}
  3233. X
  3234. X@
  3235. X
  3236. X
  3237. X4.7.2.1
  3238. Xlog
  3239. X@Start of Amiga RCS port branch.
  3240. X@
  3241. Xtext
  3242. X@d6 1
  3243. Xa6 5
  3244. X<<<<<<< rlog.c
  3245. X"$Header: /u/softeng/rsbx/rcs/amiga/RCS.cbmvax/rlog.c,v 4.7.1.1 89/08/11 01:43:14 rsbx Exp Locker: rsbx $ Purdue CS";
  3246. X=======
  3247. X"$Header: /u/softeng/rsbx/rcs/amiga/RCS/rlog.c,v 1.2 89/09/17 13:36:54 rick Exp $ Purdue CS";
  3248. X>>>>>>> 1.2
  3249. Xa41 16
  3250. X<<<<<<< rlog.c
  3251. X * Revision 4.7.1.1  89/08/11  01:43:14  rsbx
  3252. X * Start of cbmvax RCS source branch.
  3253. X * 
  3254. X * Revision 4.7  89/05/01  15:13:48  narten
  3255. X * checked in with -k by rsbx at 89.08.10.16.23.28.
  3256. X=======
  3257. X * Revision 1.2  89/09/17  13:36:54  rick
  3258. X * Port to AmigaDos done by Rick Schaeffer (ricks@@iscuva.iscs.com)
  3259. X * All changes done with conditional compile (#ifdef AMIGA).  This version
  3260. X * compiles correctly with Lattice C version 5.02 or later.
  3261. X * 
  3262. X * Revision 1.2  88/09/03  15:13:12  rick
  3263. X * Port to AmigaDos.  All done with conditional compiles
  3264. X>>>>>>> 1.2
  3265. X * 
  3266. X@
  3267. X
  3268. X
  3269. X4.7.2.2
  3270. Xlog
  3271. X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
  3272. Xsources I have here (and are later than the ones Rick used).
  3273. X@
  3274. Xtext
  3275. X@d6 5
  3276. Xa10 1
  3277. X"$Header: /u/softeng/rsbx/rcs/amiga/RCS/rlog.c,v 4.7.2.1 89/10/13 19:19:26 rsbx Exp Locker: rsbx $ Purdue CS";
  3278. Xd46 1
  3279. Xa46 3
  3280. X * Revision 4.7.2.1  89/10/13  19:19:26  rsbx
  3281. X * Start of Amiga RCS port branch.
  3282. X * 
  3283. Xd52 9
  3284. X@
  3285. X
  3286. X
  3287. X4.7.1.1
  3288. Xlog
  3289. X@Start of cbmvax RCS source branch.
  3290. X@
  3291. Xtext
  3292. X@d6 1
  3293. Xa6 1
  3294. X"$Header: /u/softeng/rsbx/rcs/rcs.uunet/src/RCS/rlog.c,v 4.7 89/05/01 15:13:48 narten Exp $ Purdue CS";
  3295. Xa41 3
  3296. X * Revision 4.7  89/05/01  15:13:48  narten
  3297. X * checked in with -k by rsbx at 89.08.10.16.23.28.
  3298. X * 
  3299. X@
  3300. SHAR_EOF
  3301. echo "End of archive 11 (of 14)"
  3302. # if you want to concatenate archives, remove anything after this line
  3303. exit
  3304.